.TITLE SYSXT .IDENT /16.07/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; D. N. CUTLER 10-AUG-73 ; ; MODIFIED FOR RSX-11M-PLUS VERSION 2.1 BY: ; ; B. S. MCCARTHY ; J. R. KAUFFMAN ; T. LEKAS ; J. M. LAWLER ; ; MODIFIED FOR RSX-11M-PLUS VERSION 3.0 BY: ; ; J. W. BERZLE ; D. R. DONCHIN ; J. R. KAUFFMAN ; T. LEKAS ; B. S. MCCARTHY ; L. B. MCCULLEY ; C. A. SILVER ; ; MODIFIED FOR RSX-11M-PLUS VERSION 4.0 BY: ; ; B. S. MCCARTHY ; K. L. NOEL ; ; MODIFIED FOR RSX-11M-PLUS VERSION 4.2 BY: ; ; P. K. M. WEISS ; B. S. MCCARTHY ; L. B. MCCULLEY ; ; MODIFIED FOR RSX-11M-PLUS V4.4 BY: ; ; J. W. BERZLE 22-MAY-1990 16.00 ; ; JWB231 -- FIX PROBLEM WHERE CONTEXT SWITCHING NO LONGER ; DISABLES WITH $CXDBL (FROM DAVE CARROLL) ; ; J. C. FRANZINI 21-AUG-90 16.01 ; JCF398 -- $FINXT: FIX PROBLEM WHERE CARRY WAS BEING SET ; WHEN ESB WAS AT 100000 OR ABOVE ; ; J. C. FRANZINI 18-MAY-92 16.02 ; JCF405 -- SCHEDULE TASKS WITH TS.CIP SET IF THEY HAVE ANY ; KERNEL ASTS. PREVIOUSLY, THESE TASKS WERE ; SCHEDULED ONLY IF THEY WERE WAITING TO EXIT. ; ; MODIFIED FOR RSX-11M-PLUS V4.5 BY: ; ; D. CARROLL 06-MAY-1993 16.03 ; DC203 -- INCLUDE SUPPORT FOR RON ACCESS ; ; D. CARROLL 17-JUN-1993 16.04 ; DC227 -- INCLUDE SUPPORT IN $SGFIN FOR UNIBUS MEMORY ; ; D. CARROLL 13-SEP-1993 16.05 ; DC235 -- DON'T USE R4 FOR AST CHECK WHEN TS.CIP IS SET ; UVO-100068 (AALSMEER) ; ; D. CARROLL 17-JAN-1995 16.06 ; DC248 -- ALLOW PRIV TASKS MAPPED TO THE EXEC TO ACCESS ; POOL WHICH MAY BE RESIDENT IN ICB POOL ; ; Modified for RSX-11M-PLUS V4.6 by: ; ; D. Carroll 18-Oct-1995 16.07 ; DC404 - Include psect definition to allow ICB pool to ; be fully utilized. ; ; ; SYSTEM ENTRANCE, EXIT, AND PROCESSOR DISPATCHING ; ; MACRO LIBRARY CALLS ; .MCALL ABODF$,HDRDF$,HWDDF$,PCBDF$,TCBDF$ .MCALL PKTDF$,ITBDF$,BGCK$A ABODF$ ;DEFINE TASK ABORT CODES HDRDF$ ;DEFINE TASK HEADER OFFSETS HWDDF$ ;DEFINE HARDWARE REGISTERS PCBDF$ ;DEFINE PARTITION CONTROL BLOCK OFFSETS TCBDF$ ;DEFINE TASK CONTROL BLOCK OFFSETS ITBDF$ ;DEFINE INTERRUPT TRANSFER BLOCK OFFSETS PKTDF$ ;DEFINE AST OFFSETS AND CODES .IIF DF,K$$DAS&I$$CBP, .PSECT EXEC1 ;DC404 ;DC404 ;+ ; **-$DIRSV-DIRECTIVE SAVE ; ; THIS ROUTINE IS CALLED FROM DIRECTIVE LEVEL TRAP SERVICE ROUTINES. THE ; STACK DEPTH IS +1, THUS A SWITCH TO THE SYSTEM STACK IS ALWAYS NEC- ; ESSARY. AT THE END OF TRAP PROCESSING A RETURN IS EXECUTED TO EXIT ; FROM THE SYSTEM. ; ; INPUTS: ; ; 4(SP)=PS WORD PUSHED BY TRAP. ; 2(SP)=PC WORD PUSHED BY TRAP. ; 0(SP)=SAVED R5 PUSHED BY 'JSR R5,$DIRSV'. ; ; OUTPUTS: ; ; REGISTER R4 IS PUSHED ONTO THE CURRENT STACK AND THEN A SWITCH ; TO THE SYSTEM STACK IS EXECUTED. REGISTERS R3 THRU R0 ARE ; PUSHED ON THE SYSTEM STACK, THE NEW PROCESSOR PRIORITY IS ; SET, AND A CALL TO THE CALLER IS EXECUTED. ;- $DIRSV::MOV R4,-(SP) ;;;SAVE REGISTER R4 ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 26. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH26==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL DEC @#$STKDP ;;;SET PROPER STACK DEPTH .IF DF M$$PRO BNE 10$ ;;;IF NE DON'T SWITCH STACKS .ENDC ; DF M$$PRO .IF NDF M$$PRO 10$: ;;; REFERENCE LABEL .IFTF ; NDF M$$PRO MTPS #0 ;;;ALLOW INTERRUPTS LOCK$ $EXECL,WAIT .IFF ; NDF M$$PRO 10$: MTPS #0 ;;;ALLOW INTERRUPTS .ENDC ; NDF M$$PRO MOV R3,-(SP) ;SAVE REGISTERS R3 THRU R0 MOV R2,-(SP) ; MOV R1,-(SP) ; MOV R0,-(SP) ; .IF DF M$$PRO MOV $TKTCB,R0 ;GET CURRENT TCB ADDRESS ASSUME T2.HLT,200 ;NEXT INSTRUCTION DEPENDS ON THIS TSTB T.ST2(R0) ;IS TASK EXITING? BPL 15$ ;IF PL NO -- ALLOW ENTRY TO SYSTEM TST $STKDP ;DID WE COME FROM USER STATE ? BEQ 20$ ;IF EQ YES - NO ACTION ALLOWED 15$: MOV (SP),R0 ;RESTORE R0 FOR $SWSTK .ENDC .IF DF R$$WPT MOV R5,$WPLST ;SAVE ADDRESS OF LAST SYSTEM ROUTINE .ENDC ; DF R$$WPT CALL (R5) ;CALL SYNCHRONOUS TRAP ROUTINE 20$: JMP $DIRXT ;+ ; **-$IFORK-INDEPENDANT $CFORK ; ; THIS ROUTINE IS SIMILAR TO $CFORK (SEE BELOW) BUT DOES NOT USE THE ; FORK BLOCK IN THE SCB. INSTEAD IT ALLOCATES A FORK BLOCK FROM THE ; POOL, TRANSFERS EXECUTION TO ANOTHER PROCESSOR, AND THEN DEALLOCATES ; THE FORK BLOCK. ; ; INPUTS: ; ; R4=ANYTHING (THIS IS SAVED). ; R5=UCB ADDRESS. ; 0(SP)=CALLER'S RETURN ADDRESS. ; 2(SP)=RETURN ADDRESS OF CALLER'S CALLER. ; ; OUTPUTS: ; ; R4=SAVED R4. ; R5=UCB ADDRESS. ; ; EXECUTION IS ON CORRECT PROCESSOR. DRIVERS WITHOUT KRB'S HAVE ; NO CORRECT PROCESSOR, AND ALWAYS EXECUTE ON THE CURRENT PROCESSOR. ;- .IF DF M$$PRO $IFORK::MOV (SP)+,R3 ;PUT RETURN ADDRESS IN PROPER PLACE FOR ;$EXDOP ;+ ; **-$EXDOP-EXECUTE DRIVER ROUTINE ON PROCESSOR ; **-$EXROP-EXECUTE ROUTINE ON PROCESSOR ; ; THIS ROUTINE IS USED TO EXECUTE A PARTICULAR ROUTINE (USUALLY IN ; A DRIVER) UNDER CONTROL OF A SPECIFIC PROCESSOR (POSSIBLY THIS ONE.) ; THE CODE SEGMENT TO BE EXECUTED MUST BE TERMINATED BY A RETURN. ; ; IF THE ROUTINE CAN BE EXECUTED ON THE CURRENT PROCESSOR, IT IS ; CALLED BY A CALL. SHOULD IT BE NECESSARY TO EXECUTE IT ON ; ANOTHER PROCESSOR, A FORK BLOCK IS ALLOCATED AND LINKED INTO ; THE FORK QUEUE. THEN A RETURN TO THE CALLER IS PERFORMED. ; WHEN THE TARGET PROCESSOR EXECUTES THE "FORKED" ROUTINE, THE ; FORK BLOCK WILL BE DEALLOCATED PRIOR TO CALLING THE ROUTINE TO ; BE EXECUTED. THIS ENTIRE OPERATION IS INDEPENDANT OF WHAT IS ; ON THE STACK, I.E. CONTROL WILL ALWAYS RETURN TO THE CALLER ; WHETHER OR NOT THE ROUTINE CAN BE EXECUTED ON THIS PROCESSOR. ; ; THE FORM OF THE FORK BLOCK IS: ; ; *-------------------------------* ; 0 ! UNIBUS RUN MASK ! ; *-------------------------------* ; 2 ! FORK LINK ! ; *-------------------------------* ; 4 ! FORK PC ! ; *-------------------------------* ; 6 ! FORK R5 ! ; *-------------------------------* ; 10 ! FORK R4 ! ; *-------------------------------* ; 12 ! DRIVER KISAR5 ! ; *-------------------------------* ; 14 ! ROUTINE ADDRESS ! ; *-------------------------------* ; ; INPUTS: ; ; R2=UNIBUS RUN MASK ($EXROP ONLY). ; R3=ADDRESS OF ROUTINE TO BE EXECUTED. ; R4=ANYTHING (THIS IS SAVED). ; R5=UCB ADDRESS ($EXDOP ONLY). ; 0(SP)=CALLER'S RETURN ADDRESS. ; 2(SP)=RETURN ADDRESS OF CALLER'S CALLER. ; ; OUTPUTS: ; ; THE ROUTINE TO BE EXECUTED IS CALLED WITH: ; ; R4=SAVED R4. ; R5=SAVED R5 (UCB ADDRESS IF ENTRY AT $EXDOP). ; 0(SP)=RETURN ADDRESS. ; ; THE CALLING ROUTINE IS RETURNED TO WITH: ; ; C=0 IF THE ROUTINE TO BE EXECUTED HAS EXECUTED. ; C=1 IF A FORK HAD TO BE CREATED. ; ; NOTE: ONLY R5 IS PRESERVED TO CALLING ROUTINE! ; ; THE CONTENTS OF KERNEL INSTR AND DATA APR 5 AT THE ; TIME OF THE CALL ARE DESTROYED. ; ;- .ENABL LSB $EXDOP::MOV U.SCB(R5),R2 ;GET SCB ADDRESS MOV S.KS5(R2),KINAR5 ;MAP DRIVER IN I SPACE .IF DF K$$DAS MOV S.KS5(R2),KDSAR5 ;MAP DRIVER IN D SPACE .ENDC $EXRP1::MOV S.URM(R2),R2 ;GET URM FROM SCB BEQ 10$ ;IF EQ NO URM $EXROP::BIT R2,@$CPURM ;CAN WE EXECUTE ON THIS PROCESSOR BEQ 20$ ;IF EQ NO, MUST FORK ; ; EXECUTE THE ROUTINE HERE AND NOW ; 10$: MOV R5,-(SP) ;SAVE R5 FROM THE ROUTINE CALL (R3) ;CALL ROUTINE MOV (SP)+,R5 ;RESTORE SAVED R5 CLC ;TELL CALLER THAT WE DID IT RETURN 20$: MOV #7.*2,R1 ;SET BLOCK SIZE FOR FORK BLOCK MOV R2,-(SP) ;SAVE R2 FROM $ALOCB CALL $ALOCB ;WE ASSUME IT SAVES R3,R4,R5 BCC 30$ ;IF CC ALLOCATION OK ; ; ***** THIS IS A RATHER NASTY SITUATION ***** ; ; WE CANNOT GET TO THE CORRECT PROCESSOR, SINCE WE CAN'T ; ALLOCATE A FORK BLOCK. NEITHER CAN WE EXIT THE EXEC TO ; LET ANYONE ELSE IN WHO MIGHT POTENTIALLY FREE UP POOL, ; SINCE WE HAVE NO IDEA WHAT THE CALLER WAS DOING. IT WOULD ; BE NICE IF IN THE FUTURE SOME WAY OUT OF THIS PROBLEM ; COULD BE DEVISED. ; BGCK$A BF.MP,BE.NPL,FATAL ;POOL FULL 30$: MOV (SP)+,(R0) ;INSERT URM IN FORK BLOCK ADD #14.,R0 ;POINT AT END OF BLOCK MOV R3,-(R0) ;INSERT ROUTINE ADDRESS MOV KINAR5,-(R0) ;PUT MAPPING IN FORK BLOCK MOV R4,-(R0) ;INSERT R4 MOV R0,R4 ;SET UP FOR $FORK1 CALL $FORK1 ;WE ASSUME $FORK ALWAYS RETURNS C=1. ; ; AT THIS POINT THE CALLER HAS BEEN RETURNED TO. ; ; WHEN WE EXECUTE THE CODE BELOW WE ARE ON THE TARGET PROCESSOR ; AND THE REGISTERS LOOK LIKE: ; ; R3=ADDRESS OF PC WORD IN FORK BLOCK. ; R4=SAVED R4. ; R5=SAVED R5 (POSSIBLY UCB ADDRESS IF ENTRY AT $EXDOP). ; MOV R3,R0 ;POINT AT PC WORD IN FORK BLOCK SUB #4,R0 ;POINT AT TOP OF BLOCK MOV #7.*2,R1 ;SET BLOCK LENGTH MOV 14(R0),-(SP) ;SAVE ADDRESS OF ROUTINE CALLR $DEACB ;DEALLOCATE BLOCK (ASSUME R4,R5 SAVED) .DSABL LSB ;AND EXIT TO OUR ROUTINE WHO WILL ;EXIT BACK TO THE FORK PROCESSOR ;+ ; **-$CFORK-CONDITIONAL FORK ; ; THIS ROUTINE WILL TRANSFER THE EXECUTION STREAM TO ANOTHER ; PROCESSOR BY USING THE FORK LIST. IT SHOULD ONLY BE CALLED ; AT EXECUTIVE LEVEL, SINCE IT USES REGISTERS OTHER THAN R4 AND ; R5. ; ; INPUTS: ; ; R4=ANYTHING. ; R5=UCB ADDRESS. ; ; OUTPUTS: ; ; R4=SAVED R4. ; R5=UCB ADDRESS. ; ; EXECUTION IS ON CORRECT PROCESSOR. NOTE: DRIVERS WITHOUT KRBS ; HAVE NO "CORRECT PROCESSOR" SO $CFORK WILL ALWAYS RETURN. ;- $CFORK::MOV U.SCB(R5),R2 ;GET SCB ADDRESS TALLY$ B.CFCL,XA$$CF ;COUNT A $CFORK CALL TST S.URM(R2) ;IS THERE A UNIBUS RUN MASK BEQ $INTXT ;IF EQ NO -- RETURN BIT S.URM(R2),@$CPURM ;OK ON THIS CPU? BNE $INTXT ;IF NE YES -- RETURN ; ; TRANSFER EXECUTION TO CORRECT PROCESSOR. ; TALLY$ B.CFRK,XA$$CF ;COUNT A $CFORK FORK MOV R4,-(SP) ;SAVE R4 MOV R2,R4 ;GET SCB ADDRESS ADD #S.FRK+6,R4 ;POINT TO END OF FORK BLOCK MOV (SP)+,(R4) ;PUT SAVED R4 IN FORK BLOCK BR $FORK1 ;TRANSFER INTO FORK ROUTINES .ENDC ; DF M$$PRO ;+ ; **-$FORK-FORK AND CREATE SYSTEM PROCESS ; ; THIS ROUTINE IS CALLED FROM AN I/O DRIVER TO CREATE A SYSTEM PROCESS THAT ; WILL RETURN TO THE DRIVER AT STACK DEPTH ZERO TO FINISH PROCESSING. ; ; INPUTS: ; ; R5=ADDRESS OF THE UCB FOR THE UNIT BEING PROCESSED. ; 0(SP)=RETURN ADDRESS TO CALLER. ; 2(SP)=RETURN ADDRESS TO CALLERS CALLER. ; ; OUTPUTS: ; ; REGISTERS R5 AND R4 ARE SAVED IN THE CONTROLLER FORK BLOCK AND ; A SYSTEM PROCESS IS CREATED. THE PROCESS IS LINKED TO THE FORK ; QUEUE AND A JUMP TO $INTXT IS EXECUTED. ;- .ENABL LSB $FORK:: MOV R4,-(SP) ;SAVE REGISTER R4 MOV U.SCB(R5),R4 ;POINT TO CONTROLLER STATUS BLOCK CLRB S.CTM(R4) ;DISABLE TIMEOUT ADD #S.FRK+6,R4 ;POINT TO END OF FORK BLOCK MOV (SP)+,(R4) ;PUT SAVED R4 IN FORK BLOCK ;+ ; **-$FORK1-FORK AND CREATE SYSTEM PROCESS ; ; THIS ROUTINE IS AN ALTERNATE ENTRY TO CREATE A SYSTEM PROCESS AND ; SAVE REGISTER R5. ; ; INPUTS: ; ; R4=ADDRESS OF THE LAST WORD OF A 3 WORD FORK BLOCK PLUS 2. ; R5=REGISTER TO BE SAVED IN THE FORK BLOCK. ; ; OUTPUTS: ; ; REGISTER R5 IS SAVED IN THE SPECIFIED FORK BLOCK AND A SYSTEM ; PROCESS IS CREATED. THE PROCESS IS LINKED TO THE FORK QUEUE ; AND A JUMP TO $INTXT IS EXECUTED. ; R5 IS PRESERVED FOR CALLERS CALLER. ;- $FORK1::MOV R5,-(R4) ;SAVE REGISTER R5 ;+ ; **-$FORK0-FORK AND CREATE SYSTEM PROCESS ; ; THIS ROUTINE IS AN ALTERNATE ENTRY TO CREATE A SYSTEM PROCESS. ; ; INPUTS: ; ; R4=ADDRESS OF THE LAST WORD OF A 2 WORD FORK BLOCK PLUS 2. ; ; OUTPUTS: ; ; A SYSTEM PROCESS IS CREATED, LINKED TO THE FORK QUEUE AND A ; JUMP TO $INTXT IS EXECUTED. ;- $FORK0::MOV (SP)+,-(R4) ;SET FORK PC CLR -(R4) ;CLEAR LINK TO NEXT FORK BLOCK ;+ ; **-$QFORK-INSERT FORK BLOCK AT END OF FORK QUEUE ; ; THIS ROUTINE IS AN ALTERNATE ENTRY TO QUEUE A FORK BLOCK ; AND RETURN TO THE CALLER. IT DOES NOT RETURN TO THE CALLER'S ; CALLER AS DO THE OTHER FORK ROUTINES. ; ; INPUTS: ; ; R4=ADDRESS OF A FORK BLOCK. ; ; OUTPUTS: ; ; THE FORK BLOCK SUPPLIED IN R4 IS LINKED INTO THE SYSTEM ; FORK QUEUE, AND A RETURN TO THE CALLER IS EXECUTED. ;- $QFORK::MFPS -(SP) ;SAVE PRIORITY AROUND QUEUE INSERTION MTPS #PR7 ;CAN'T INTERRUPT QUEUE INSERTION LOCK$ $FORKL,SPIN ;;;SERIALIZE ACCESS TO QUEUE .IF DF R$$FRK MOV R4,-(SP) ;;;FREE A REGISTER MOV #$FRKHD,R4 ;;;GET THE FORK LISTHEAD 10$: MOV (R4),R4 ;;;GET THE NEXT ELEMENT IN THE LIST BEQ 15$ ;;;IF EQ NO MORE - GO ON CMP R4,(SP) ;;;THIS ONE IN THE LIST ALREADY? BNE 10$ ;;;IF NE NO - LOOK SOME MORE BGCK$A BF.INT,BE.2FR,FATAL ;;;DOUBLE FORK 15$: MOV (SP)+,R4 ;;;RESTORE R4 .ENDC ;R$$FRK MOV R4,@$FRKHD+2 ;;;LINK NEW ENTRY TO OLD LAST MOV R4,$FRKHD+2 ;;;SET ADDRESS OF NEW LAST .IF DF M$$PRO ; ; ADD ITEM TO FORK LIST WAIT MASK. ; TST -(R4) ;;;IS IT LEGAL FORK BLOCK? BEQ 40$ ;;;IF EQ YES BIT (R4),$URMST ;;;IS URM ONLINE? BNE 40$ ;;;IF NE YES BGCK$A BF.MP,BE.URM,FATAL ;;;FORK BLOCK FOR OFFLINE URM 40$: BIS (R4)+,$IIPND ;;;ADD TO FORK WAIT MASK .ENDC TSTB $IDLFL ;;;ARE WE IN IDLE LOOP NOW? BLE 50$ ;;;IF LE NO ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 32. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH32==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL .IF DF M$$PRO COMB @#$IDLFL ;;;SHOW WE HAVE BEEN HERE MOV #DIRXT2,$STACK-24 ;;;FORCE SYSTEM BACK THRU $IIPND CHECK .IFF CLRB @#$IDLFL ;;;NOT IN IDLE LOOP ANYMORE MOV #$DIRXT,$STACK-24 ;;;FORCE SYSTEM BACK THRU LOCK AND INTO ;;;EXEC .ENDC 50$: ULOCK$ $FORKL,SPIN MTPS (SP)+ ;;;RESTORE OLD PRIORITY SEC ;RETURN WITH CARRY SET TO CALLERS CALLER RETURN ; .DSABL LSB ;+ ; **-$FORK2-FORK ROUTINE FOR USE IN CONJUNCTION WITH ; THE CINT$ DIRECTIVE. ; ; INPUTS: ; ; R5=ADDRESS OF FORK BLOCK IN ITB ; ; OUTPUTS: ; ; IF THE FORK BLOCK IS ALREADY IN USE (FORK PC NON-ZERO), ; A SYSTEM PROCESS IS CREATED, LINKED TO THE FORK QUEUE AND A ; JUMP TO $INTXT IS EXECUTED. ; ELSE THE INTERRUPT IS DISMISSED (NO RETURN TO CALLER). ; ; IMMEDIATELY ON RETURN FROM THIS ROUTINE, THE FOLLOWING ; INSTRUCTION SHOULD BE EXECUTED: ; ; CLR @R3 ; ; WHICH DECLARES THE FORK BLOCK FREE. ;- .IF DF C$$INT $FORK2::TST 2(R5) ;;;FORK BLOCK ALREADY IN USE? BNE 10$ ;;;Y - JUMP MOV R4,6(R5) ;;;SAVE R4 IN FORK BLOCK MOV R5,R4 ;;; ADD #6,R4 ;;;POINT JUST AFTER 3-WORD FORK BLOCK BR $FORK1 ;;; 10$: TST (SP)+ ;;;CLEAR STACK ;;;FALL THRU TO $INTXT .ENDC ;+ ; **-$INTXT-INTERRUPT EXIT ; ; THIS ROUTINE MAY BE CALLED VIA A JMP TO EXIT FROM AN INTERRUPT. ; ; INPUTS: ; ; 0(SP)=INTERRUPT SAVE RETURN ADDRESS. ; ; OUTPUTS: ; ; A RETURN TO INTERRUPT SAVE IS EXECUTED. ;- $INTXT::RETURN ; ;+ ; **-$INTSI-INTERRUPT SAVE (CALLED FROM INTERRUPT CONTROL BLOCKS) ; ; THIS ROUTINE IS CALLED FROM AN INTERRUPT CONTROL BLOCK. IT PUTS ; THE WORLD IN ORDER FOR ENTRY TO A DRIVER INTERRUPT ENTRY POINT AND ; MAPS TO THE DRIVER. ; ; INPUTS: ; ; 4(SP)=PS WORD PUSHED BY INTERRUPT ; 2(SP)=PC WORD PUSHED BY INTERRUPT ; 0(SP)=SAVED R5 PUSHED BY 'JSR R5,$INTSI' ; 0(R5)=SCRATCH WORD OF ICB ; 2(R5)=WORD FOR APR5 (TO MAP TO DRIVER) ; 4(R5)=BYTE FOR PS (DEVICE PRIORITY) ; 6(R5)=DRIVER INTERRUPT ENTRY POINT (BIASED BY 120000) ; ; OUTPUTS: ; ; R4 IS PUSHED ONTO CURRENT STACK ; R4 IS SET TO CONTROLLER NUMBER * 2 ; STACK DEPTH IS DECREMENTED AND, IF RESULT IS ZERO, A SWITCH ; TO THE SYSTEM STACK IS EXECUTED ; KERNEL APR5 MAPPING IS SAVED ; CPU PRIORITY IS SET TO PRIORITY FROM ICB ; DRIVER INTERRUPT ENTRY POINT IS CALLED AS A COROUTINE (SO AFTER ; A RETURN, APR5 CAN BE RESTORED) ;- $INTSI::JSR R4,(PC) ;;;SAVE R4 WHILE PRESERVING CC'S MFPS R4 ;;;RETRIEVE CONTROLLER INDEX BIC #177760,R4 ;;;CLEAR ALL BUT CONTROLLER NUMBER ASL R4 ;;;CONVERT TO WORD INDEX ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 27. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH27==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL DEC @#$STKDP ;;;SWITCH STACKS? 10$: MOV KINAR5,-(SP) ;;;SAVE KERNEL INSTRUCTION APR5 .IF DF K$$DAS MOV KDSAR5,-(SP) ;;;SAVE KERNEL DATA APR5 MOV (R5),KDSAR5 ;;;MAP TO DRIVER .ENDC MOV (R5)+,KINAR5 ;;; .IF DF C$$INT BR $INTS2 ;;;CONTINUE IN COMMON CODE .IFF .IIF NE <.-$INTS2>, .ERROR ;$INTS2 NOT THE NEXT INSTRUCTION .ENDC ;+ ; **-$INTSC-INTERRUPT SAVE (INTERRUPT FROM VECTOR CONNECTED ; TO VIA CINT$ DIRECTIVE). ; ; CALLS ISR WITH R4 AND R5 SAVED AND: ; ; R5 POINTER TO FORK BLOCK IN ITB ; PRI TAKEN FROM ITB ; ;- .IF DF C$$INT $INTSC::MOV R4,-(SP) ;;;SAVE R4 ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 28. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH28==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL DEC @#$STKDP ;;;SWITCH STACKS? 10$: MOV KINAR5,-(SP) ;;;SAVE KERNEL INSTRUCTION APR5 .IF DF K$$DAS MOV KDSAR5,-(SP) ;;;SAVE KERNEL DATA APR5 MOV X.REL-X.PSW(R5),KDSAR5 ;;;MAP TO ISR .ENDC MOV X.REL-X.PSW(R5),KINAR5 ;;; .ENDC $INTS2: MTPS (R5)+ ;;;LOAD ISR PRIORITY BISB (R5)+,R4 ;;;ADD CONSTANT TO CONTROLLER NUMBER CACHE$ SAVE ;;;SAVE BYPASS STATE OF CACHE .IF DF R$$RSV MOV R3,-(SP) ;;;SAVE REGISTERS MOV R2,-(SP) ;;; MOV R1,-(SP) ;;; MOV R0,-(SP) ;;; .IFTF $WPIN0::CALL @(R5)+ ;;;CALL ISR .IF DF R$$WPT NOP ;;;SPACE TO PLUG WATCHPOINT JSR .ENDC ; R$$WPT .IFT CMP (SP)+,R0 ;;;MAKE SURE DRIVER DIDN'T DESTROY REGS BEQ 30$ ;;;IF EQ R0 IS UNMODIFIED 20$: BGCK$A BF.INT,BE.ISR,FATAL ;;;DRIVER DESTROYED REGS IN ISR 30$: CMP (SP)+,R1 ;;;HAS R1 BEEN MODIFIED? BNE 20$ ;;;IF NE YES CMP (SP)+,R2 ;;;HAS R2 BEEN MODIFIED? BNE 20$ ;;;IF NE YES CMP (SP)+,R3 ;;;HAS R3 BEEN MODIFIED? BNE 20$ ;;;IF NE YES .ENDC CACHE$ UNSAVE ;;;RESTORE BYPASS STATE OF CACHE .IF DF K$$DAS MOV (SP)+,KDSAR5 ;;;RESTORE KERNEL DATA APR5 .ENDC MOV (SP)+,KINAR5 ;;;RESTORE KERNEL INSTRUCTION APR5 BR $INTX1 ;;;EXIT FROM INTERRUPT .IF DF R$$WPT $WPIN3::MOV R5,$WPLST ;SAVE ADDRESS OF LAST SYSTEM ROUTINE CALL (R5) ;CALL THE CALLER BACK BR WPIN4 ;FINISH IN COMMON CODE $WPIN2::MOV (R5),$WPLST ;SAVE ADDRESS OF LAST SYSTEM ROUTINE CALL @(R5)+ ;CALL ISR WPIN4:: CMP $WPVAL,@$WPADR ;DID WATCHED LOCATION CHANGE ? BEQ 1$ ;IF EQ NO (ONE OF THESE IS NOP'D BY BNE 1$ ;IF NE NO THE SET WATCH COMMAND) BPT ;LET XDT KNOW ABOUT IT 1$: RETURN ;RETURN TO PROPER REAL INTS.. ROUTINE .ENDC ; DF R$$WPT ;+ ; **-$INTSV-INTERRUPT SAVE ; **-$INTSE-INTERRUPT SAVE FOR ERRORLOGGING DEVICES ; ; THIS ROUTINE IS CALLED FROM AN INTERRUPT SERVICE ROUTINE WHEN AN ; INTERRUPT IS NOT GOING TO BE IMMEDIATELY DISMISSED. A SWITCH TO ; THE SYSTEM STACK IS EXECUTED IF THE CURRENT STACK DEPTH IS +1. WHEN ; THE INTERRUPT SERVICE ROUTINE FINISHES ITS PROCESSING, IT EITHER FORKS ; , JUMPS TO $INTXT, OR EXECUTES A RETURN. ; ; INPUTS: ; ; 4(SP)=PS WORD PUSHED BY INTERRUPT. ; 2(SP)=PC WORD PUSHED BY INTERRUPT. ; 0(SP)=SAVED R5 PUSHED BY 'JSR R5,$INTSV'. ; 0(R5)=NEW PROCESSOR PRIORITY. ; ; OUTPUTS: ; ; REGISTER R4 IS PUSHED ONTO THE CURRENT STACK AND THE CURRENT ; STACK DEPTH IS DECREMENTED. IF THE RESULT IS ZERO, THEN ; A SWITCH TO THE SYSTEM STACK IS EXECUTED. THE NEW PROCESSOR ; STATUS IS SET AND A CO-ROUTINE CALL TO THE CALLER IS EXECUTED ; R4 IS SET WITH THE CONTROLLER INDEX*2, WHICH IS DETERMINED ; FROM THE PSW AT ENTRY. ;- $INTSE:: ;;;REFERENCE LABEL $INTSV::JSR R4,(PC) ;;;SAVE R4 WHILE PRESERVING CC'S MFPS R4 ;;;RETRIEVE CONTROLLER INDEX BIC #177760,R4 ;;;MASK OFF CONTROLLER NUMBER ASL R4 ;;;CONVERT TO WORD INDEX 2$: ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 29. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH29==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL DEC @#$STKDP ;;;SWITCH STACKS? .IF DF K$$DAS 3$: MOV PS,-(SP) ;;;SAVE CURRENT PS WORD BIC #PMODE,PS ;;;SET PREVIOUS MODE TO KERNEL MFPI (R5)+ ;;;RETRIEVE CLEAR MASK FOR NEW PRIORITY BIC (SP)+,(SP) ;;;CLEAR FOR NEW PRIORITY MOV (SP)+,PS ;;;SET NEW PRIORITY .IFF 3$: BIC (R5)+,PS ;;;LOAD NEW PRIORITY .ENDC CACHE$ SAVE ;;;SAVE BYPASS STATE OF CACHE $WPIN1::CALL (R5) ;;;CALL THE CALLER BACK .IF DF R$$WPT NOP ;;;SPACE TO PLUG WATCHPOINT JSR .ENDC ; R$$WPT $INTSF::CACHE$ UNSAVE ;;;RESTORE BYPASS STATE OF CACHE ;+ ; **-$INTXT-INTERRUPT EXIT ; ; THIS ROUTINE IS ENTERED VIA A RETURN TO EXIT FROM AN INTERRUPT. IF THE ; STACK DEPTH IS NOT EQUAL TO ZERO, THEN REGISTERS R4 AND R5 ARE ; RESTORED AND AN RTI IS EXECUTED. ELSE A CHECK IS MADE TO SEE ; IF THERE ARE ANY ENTRIES IN THE FORK QUEUE. IF NONE, THEN R4 AND ; R5 ARE RESTORED AND AN RTI IS EXECUTED. ELSE REGISTERS R3 THRU ; R0 ARE SAVED ON THE CURRENT STACK AND A DIRECTIVE EXIT IS EXECUTED. ; ; INPUTS: (MAPPED SYSTEM) ; ; 06(SP)=PS WORD PUSHED BY INTERRUPT. ; 04(SP)=PC WORD PUSHED BY INTERRUPT. ; 02(SP)=SAVED R5. ; 00(SP)=SAVED R4. ;- .ENABL LSB $INTX1::MTPS #PR7 ;;;LOCK OUT INTERRUPTS TST $STKDP ;;;STACK DEPTH ZERO? BEQ 2$ ;;;IF EQ YES JMP 10$ ;;;IF NE NO 2$: ;;;REFERENCE LABEL .IF NDF M$$PRO TST $FRKHD ;;;ANYTHING IN FORK QUEUE? BEQ 10$ ;;;IF EQ NO .IFF CACHE$ BYPASS ;;;SEE IF THERE IS ANY WORK MOV $IIPND,R4 ;;;GET URM NEEDING WORK MOV $IICPU,R5 ;;;GET THOSE WITH INTS PENDING CACHE$ RESTOR BIC @$CPURM,R5 ;;;DON'T CONSIDER OURSELVES INTERRUPTED BIC R5,R4 ;;;CLEAR THOSE PEOPLE WITH INTS PENDING BEQ 10$ ;;;IF EQ NO WORK FOR US OR ANYONE NOT ;;;ALREADY INTERRUPTED .ENDC ; ; ENTER THE EXECUTIVE. THERE IS EITHER WORK SPECIFICALLY FOR US, OR ; WORK FOR SOMEONE NOT CURRENTLY INTERRUPTED. ; 3$: MTPS #0 ;;;ALLOW INTERRUPTS MOV R3,-(SP) ;SAVE REGISTERS R3 THRU R0 MOV R2,-(SP) ; MOV R1,-(SP) ; MOV R0,-(SP) ; 4$: LOCK$ $EXECL,WAIT ;+ ; **-$DIRXT-DIRECTIVE EXIT ; ; THIS ROUTINE IS CALLED VIA A JUMP TO EXIT FROM A DIRECTIVE OR TRAP ; SERVICE ROUTINE. IF THERE ARE ANY ENTRIES IN THE FORK QUEUE, THEN ; THE FIRST ENTRY IS REMOVED AND THE FORK ROUTINE IS EXECUTED. ELSE ; A CHECK IS MADE TO SEE IF REDISPATCHING OF THE PROCESSOR IS NECES- ; SARY. IF NOT, THEN REGISTERS R0 THRU R5 ARE RESTORED AND AN RTI ; IS EXECUTED. ELSE THE PROCESSOR IS REDISPATCHED AND THE EXIT ; SEQUENCE IS EXECUTED AGAIN. ; ; INPUTS: (MAPPED SYSTEM) ; ; 16(SP)=PS WORD PUSHED BY INTERRUPT OR TRAP. ; 14(SP)=PC WORD PUSHED BY INTERRUPT OR TRAP. ; 12(SP)=SAVED R5. ; 10(SP)=SAVED R4. ; 06(SP)=SAVED R3. ; 04(SP)=SAVED R2. ; 02(SP)=SAVED R1. ; 00(SP)=SAVED R0. ;- .IF DF M$$PRO $DIRXT::CLR R5 ;INITIALIZE TCB POINTER DIRXT1: MTPS #PR7 ;;;LOCK OUT INTERRUPTS .IF DF R$$WPT CMP $WPVAL,@$WPADR ;;;WATCHPOINT STILL OK ? ;;;ONE OF THE FOLLOWING BRANCHES ;;;SHOULD BE NO-OPED TO START THE ;;;WATCHPOINTS $WPBR:: BEQ 1$ ;;;IF EQ STILL OK BNE 1$ ;;;IF NE STILL OK BPT ;;;OOOOOOPPPPPSSS!!! 1$: ;;;REFERENCE LABEL .ENDC ; DF R$$WPT CACHE$ BYPASS MOV $IIPND,R3 ;;;ANY WORK IN FORK QUEUE? CACHE$ RESTOR BIT @$CPURM,R3 ;;;ANY WORK? BNE 20$ ;;;IF NE YES .IFF $DIRXT::MTPS #PR7 ;;;LOCK OUT INTERRUPTS .IF DF R$$WPT CMP $WPVAL,@$WPADR ;;;WATCHPOINT STILL OK ? ;;;ONE OF THE FOLLOWING BRANCHES ;;;SHOULD BE NO-OPED TO START THE ;;;WATCHPOINTS $WPBR:: BEQ 1$ ;;;IF EQ STILL OK BNE 1$ ;;;IF NE STILL OK BPT ;;;OOOOOOPPPPPSSS!!! 1$: ;;;REFERENCE LABEL .ENDC ; DF R$$WPT MOV $FRKHD,R3 ;;;ANYTHING IN FORK QUEUE BNE 20$ ;;;IF NE YES .ENDC ; ; EVEN IF CONTEXT SWITCHING IS DISABLED, WE STILL NEED TO SERVICE ASTS. ; AND WE NEED TO SERVICE KERNAL ASTS EVEN IF THE TASK IS EXITING. ; TSTB $CXDBL ;;;IS CONTEXT SWITCHING DISABLED? BEQ 5$ ;;;IF EQ NO MOV $TKTCB,R5 ;;;PICK UP CURRENT TASK TCB ADDRESS MOV T.ASTL(R5),R4 ;;;AST QUEUED FOR THIS TASK? BNE 53$ ;;;IF NE YES TSTB T.ST2(R5) ;;;TASK EXITING (DUE TO ABORT)? BPL 6$ ;;;IF PL NO 52$: JMP TEXIT ;;;INITIATE TASK EXIT 53$: TSTB A.CBL(R4) ;;; KERNEL AST PENDING? BMI 54$ ;;; ALWAYS DO KERNEL AST'S TSTB T.ST2(R5) ;;; TASK EXITING? BMI 52$ ;;; CONTINUE RUNDOWN ; ; CHECK IF USER MODE AST'S ARE IN PROGRESS, OR DISABLED. ; BIT #T2.AST!T2.DST,T.ST2(R5) ;;; AST ACTIVE OR DISBLED? BNE 6$ ;;; IF NE, YES, DON'T EXECUTE AST 54$: MTPS #0 ;;;ALLOW INTERRUPTS JMP TAST ;GO DO THE AST 5$: MOV @$RQSCH,R5 ;;;SCHEDULING REQUESTED? BEQ 6$ ;;;IF EQ NO JMP 40$ ;;;IF NE YES 6$: ULOCK$ $EXECL,WAIT ;;;RELEASE EXECUTIVE ; ; CHECK TO SEE IF THERE IS ANY WORK FOR THE EXECUTIVE TO DO. ; ; THIS SECTION OF CODE MAY BE ENTERED FROM A NUMBER OF AREAS: ; ; 1. FROM THE ENTRANCE TO THE IDLE LOOP AFTER PR7 ; UNLOCKING THE EXECUTIVE. ; ; 2. AFTER UNLOCKING THE EXECUTIVE IN $DIRXT PR7 ; JUST PRIOR TO RESTORING THE REGISTERS. ; ; 3. FROM ANY NON-PR7 SECTION OF CODE IN THE PR0 ; IDLE LOOP. IN THIS CASE, WE CAN NOT BE ; JERKED OUT OF THIS CODE SINCE $IDLFL IS ; NEGATIVE, INFORMING $QFORK NOT TO CRAM ; THE STACK WITH THE ADDRESS OF DIRXT2. ; ; --------- ; ; THIS SECTION OF CODE HAS THREE OUTCOMES: ; ; ; 7$: THERE IS NO CURRENT WORK FOR US, BUT WORK IS PENDING FOR ; ANOTHER CPU. INTERRUPT THEM AND CHECK OUR WORK PENDING ONCE ; MORE BEFORE EXITING AT 8$. ; ; 8$: THERE IS NO WORK FOR US AND NO WORK PENDING FOR ANY OTHER ; CPU. WE WILL EXIT BACK TO WHENCE WE CAME; THE IDLE LOOP ; OR AN ACTIVE USER TASK. ; ; 15$: THERE DEFINATELY WORK FOR US, SO WE REENTER THE EXECUTIVE, ; CLEARING THE IDLE FLAG ($IDLFL) IN CASE WE CAME FROM THE ; IDLE LOOP. ; .IF DF M$$PRO DIRXT2: CACHE$ BYPASS MOV $IIPND,R4 ;;;GET PENDING URM BEQ 8$ ;;;IF EQ NO WORK BIT @$CPURM,R4 ;;;ANY WORK FOR US BNE 15$ ;;;IF NE YES BIC $IICPU,R4 ;;;CLEAR THOSE ALREADY INTERRUPTED BEQ 8$ ;;;IF EQ NO NEW WORK MOVB $EXECL+1,R5 ;;;GET PROCESSOR IN EXEC (IF ANY) BMI 7$ ;;;IF MI NO ONE IN EXEC ASL R5 ;;;MAKE CPU ID INTO WORD INDEX BIC $URMTB(R5),R4 ;;;ANY WORK HE CAN'T HANDLE BEQ 8$ ;;;IF EQ NO ; ; INTERRUPT OTHER CPU ; 7$: CACHE$ RESTOR CALL $IISVC ;INTERRUPT OTHER CPU CACHE$ BYPASS ;;;AVOID STALE DATA BIT @$CPURM,$IIPND ;;;ANY LAST NSEC WORK FOR US BNE 15$ ;;;IF NE YES -- ENTER EXEC ; ; EXIT EXECUTIVE TO USER TASK OR IDLE LOOP ; 8$: CACHE$ RESTOR TSTB $IDLFL ;;;ARE WE IN IDLE LOOP BEQ 9$ ;;;IF EQ NO MOVB #1,$IDLFL ;;;SET IN IDLE LOOP MOV #$IDLPT,R1 ;;;RESTORE REGISTER FOR IDLE LOOP MTPS #0 ;;;ALLOW INTERRUPTS JMP IDLE ;EXIT BACK TO IDLE LOOP .IFTF 9$: MOV (SP)+,R0 ;;;RESTORE REGISTERS R0 THRU R3 MOV (SP)+,R1 ;;; MOV (SP)+,R2 ;;; MOV (SP)+,R3 ;;; 10$: ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 30. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH30==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL INC @#$STKDP ;;;INCREMENT STACK DEPTH MOV (SP)+,R4 ;;;RESTORE REGISTERS R4 AND R5 MOV (SP)+,R5 ;;; ;+ ; NONSENSE INTERRUPT ENTRY/EXIT ;- $NONSI::RTI ;;; .IFT ; ; ENTER EXECUTIVE FROM EXIT OF $DIRXT OR FROM IDLE LOOP. ; ; THE ONLY DIFFERENCE BETWEEN THE TWO ENTRY CONDITIONS IS THAT IF WE ; ARE ENTERING FROM THE IDLE LOOP, THEN WE MUST CLEAR OUT THE $IDLFL ; SINCE WE ARE NOT GOING TO BE IDLE ANYMORE. OTHERWISE $IDLFL IS ALREADY ; ZERO. ; 15$: CACHE$ RESTOR ;;;RESTORE CACHE STATE CLRB $IDLFL ;;;SHOW NOT IN IDLE LOOP WHETHER WE WERE MTPS #0 ;;;OR NOT BR 4$ ;;;ENTER EXECUTIVE .ENDC ; DF M$$PRO ; ; EXECUTE FORK ROUTINE ; ; FORK ROUTINES ARE ENTERED VIA A CALL WITH THE ARGUMENTS: ; ; R3=ADDRESS OF THE BEGINNING OF THE FORK BLOCK+2. ; R4=RESTORED FROM FORK BLOCK. ; R5=RESTORED FROM FORK BLOCK. ; 20$: MTPS #PR7 LOCK$ $FORKL,SPIN .IF DF M$$PRO MOV #$FRKHD,R3 ;;;GET "CURRENT" ENTRY 22$: MOV R3,R2 ;;;MAKE CURRENT INTO PREVIOUS ENTRY MOV (R2),R3 ;;;GET NEW CURRENT -- AT END OF LIST? BNE 24$ ;;;IF NE NO ; ; END OF FORK LIST. IF WE GET TO HERE THEN WE HAVENT FOUND ANYTHING ; TO DO IN THIS PASS. WE CAN NOW CLEAR OUT OUR URM BITS FROM ; THE PENDING URM MASK, $IIPND. ; BIC @$CPURM,$IIPND ;;;CLEAR OUT OUR BITS BIC @$CPURM,$IICPU ;;;CLEAR OUT OUR BITS BR 30$ ;;;EXIT FROM FORK PROCESSING 24$: BIT -2(R3),@$CPURM ;;;IS THIS FORK BLOCK FOR US? BNE 26$ ;;;IF NE YES TST -2(R3) ;;;CAN ANY CPU PROCESS IT? BNE 22$ ;;;IF NE NO -- GO GET NEXT ONE 26$: INC $FRKCT ;;;BUMP FORK DEQUEUED COUNT MOV (R3),(R2) ;;;LINK NEXT TO PREVIOUS BNE 30$ ;;;IF NE NOT NEW LAST MOV R2,$FRKHD+2 ;;;SET NEW LAST .IFF MOV $FRKHD,R3 ;;;GET FIRST ENTRY MOV (R3),$FRKHD ;;;REMOVE ENTRY FROM FORK QUEUE BNE 30$ ;;;IF NE NOT LAST MOV #$FRKHD,$FRKHD+2 ;;;RESET FORK QUEUE LISTHEAD .ENDC 30$: ULOCK$ $FORKL,SPIN MTPS #0 .IF DF M$$PRO TST R3 ;DO WE HAVE A FORK BLOCK? BNE 35$ ;IF NE YES -- PROCESS IT JMP $DIRXT ;GO BACK TO CYCLE THRU AGAIN 35$: ;REFERENCE LABEL .ENDC MTPS #0 ;;;ALLOW INTERRUPTS ADD #10,R3 ;POINT PAST SAVED R4 .IF DF K$$DAS MOV (R3),KDSAR5 ;MAP DRIVER .ENDC ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 72. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH72==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL MOV (R3),@#KINAR5 ; MOV -(R3),R4 ;RESTORE REGISTERS R4 AND R5 MOV -(R3),R5 ; .IF DF R$$WPT MOV -2(R3),$WPLST ;SAVE ADDRESS OF LAST SYSTEM ROUTINE .ENDC ; DF R$$WPT CALL @-(R3) ;CALL FORK ROUTINE JMP $DIRXT ;TRY EXIT AGAIN ; ; RESCHEDULING OR POWERFAIL ; 40$: MTPS #0 ;;;ALLOW INTERRUPTS .IF DF P$$RFL TST $PWRFL ;POWER FAILURE? BEQ RESCH ;IF EQ NO CALL $POWER ;EXECUTE POWER RECOVERY ROUTINES .IF DF M$$PRO MOV @$RQSCH,R5 ;RENEW VALUE OF RESCHEDULE POINTER .IFF JMP $DIRXT ;CYCLE BACK THRU $DIRXT .ENDC .ENDC ; DF P$$RFL .DSABL LSB ; ; RESCHEDULING REQUESTED ; .ENABL LSB RESCH: CLR @$RQSCH ;CLEAR SCHEDULE REQUESTS .IF DF M$$PRO ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 71. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH71==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL MOV @#$TKTCB,R4 ;FETCH CURRENT TASK TCB BEQ 4$ ;IF EQ NO CURRENT TCB BIC #TS.RUN,T.STAT(R4) ;REMOVE RUNNING BIT BIT #TS.CKR,T.STAT(R4) ;CHECKPOINT REQUESTED THIS TASK? BEQ 4$ ;IF EQ NO BIC #TS.CKR,T.STAT(R4) ;CLEAR THE REQUEST ADD #T.ATT,R4 ;POINT TO ATTACHMENT DESCR LISTHEAD 3$: MOV (R4),R4 ;GET NEXT ATTACHMENT DESCR BEQ 4$ ;IF EQ THERE IS NONE MOV A.PCB-A.TCBL(R4),R1 ;POINT TO ATTACHED PCB BIT #PS.CKR,P.STAT(R1) ;CHECKPOINT REQUEST THIS PCB? BEQ 3$ ;IF EQ NO BIC #PS.CKR,P.STAT(R1) ;CLEAR CHECKPOINT REQUEST CALL $ICHKP ;TRY TO CHECKPOINT NOW BR 3$ ; ; ; IF CPU IS GOING OFFLINE, THEN GO STRAIGHT TO IDLE LOOP. DON'T ENTER ; SCHEDULING LOOP. DON'T PASS GO. DON'T COLLECT 200$. ; 4$: BIT $CPBIT,$URMST ;IS CPU GOING OFFLINE? BNE 5$ ;IF NE NO CLR R5 ;SIMULATE SCHED. LOOP FAILURE BR 33$ ;MOVE TOWARD IDLE STATE .IFF ;M$$PRO ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 71. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH71==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL .ENDC 5$: MOV #T2.STP!T2.SPN!T2.WFR,R1 ;SET STP,SPN, AND WFR MASK MOV #T2.WFR,R4 ;SET WAITFOR MASK MOV #T2.SEF,R0 ;SET STOPFOR MASK 10$: MOV T.ST2(R5),R3 ;PICK UP CONTENTS OF SECOND STATUS WORD MOV T.STAT(R5),R2 ;TASK BLOCKED ? BNE 25$ ;IF NE YES .IF DF M$$PRO BIT @$CPCRM,T.RRM(R5) ;CAN TASK RUN ON THIS PROCESSOR? BNE 30$ ;NO IF NE BIT #T4.SNC,T.ST4(R5) ;TASK USE COMMONS FOR SYNCHRONIZATION? BEQ 15$ ;IF EQ NO BIT #T2.ABO!T2.HLT,T.ST2(R5) ;TASK EXITTING OR ABORTED? BNE 15$ ;IF NE YES IT CAN RUN MOV T.PCB(R5),R2 ;GET TASK REGION PCB ADDRESS .IF DF X$$HDR MOV P.HDR(R2),-(SP) ;GET VIRTUAL ADDRESS OF HEADER BNE 12$ ;IF NE, RESIDENT HEADER MOV P.REL(R2),KISAR6 ;MAP TO EXTERNAL HEADER MOV #140000,(SP) ;SET VIRTUAL ADDRESS OF HEADER 12$: MOV (SP)+,R2 ;GET VIRTUAL ADDRESS OF HEADER .IFF ; DF X$$HDR MOV P.HDR(R2),R2 ;GET ADDRESS OF HEADER .IFTF ; DF X$$HDR CALL $CKMAP ;ANOTHER TASK MAPPED TO SAME REGION ? .ENDC ; DF X$$HDR BCS 30$ ;IF CS YES, SKIP THIS TASK MOV T.ST2(R5),R3 ;RESTORE CONTENTS OF SECOND STATUS WORD 15$: ;REFERENCE SYMBOL .ENDC MOV T.ASTL(R5),R2 ;AST QUEUED? BEQ 20$ ;IF EQ NO BIT #T2.AST!T2.DST,R3 ;AST IN PROGRESS OR DISABLED? BEQ 70$ ;IF EQ NO TSTB A.CBL(R2) ;BUFFERED I/O REQUEST? BMI 70$ ;IF MI YES 20$: BIT R1,R3 ;IS TASK STOPPED,SUSPENDED, OR IN WFR? BEQ 60$ ;NO, RESTART THIS TASK BIT R4,R3 ;WAITFOR STATE? BEQ 30$ ;IF EQ NO, SKIP THIS TASK ASSUME T2.HLT,200 ;T2.HLT MUST BE SIGN BIT TSTB T.ST2(R5) ;TASK MARKED FOR EXIT OR ABORT ? BMI 50$ ;IF MI YES BIT T.EFLM(R5),@T.EFLM+2(R5) ;WAITFOR SATISFIED ? BNE 50$ ;IF NE YES BIT R0,R3 ;TASK IN STOPFOR STATE ? BEQ 30$ ;IF EQ NO BIT #T2.AST!T2.STP,R3 ;TASK STOPPED OR AT AST STATE? BNE 30$ ;IF NE YES BIT #T2.SEF,R3 ;TASK STOPPED FOR EVENT FLAG ? BNE 24$ ;IF NE YES TSTB T.TIO(R5) ;TASK HAVE ACTIVE BUFFERED I/O ? BEQ 30$ ;IF EQ NO, GO TO NEXT TASK 24$: MOV R5,R0 ;COPY TCB ADDRESS CALL $STPTK ;STOP THE TASK BR 5$ ;BRANCH TO SET UP REGISTERS AGAIN 25$: BIC #TS.BLC,R2 ;TASK BLOCKED FOR CHECKPOINT ONLY ? BNE 29$ ;IF NE NO, CANNOT REQUEST THIS TASK BIT #T2.STP,R3 ;TASK STOPPED BEQ 30$ ;IF EQ NO, DON'T UNSTOP BIT R0,R3 ;TASK IN STOPFOR STATE ? BEQ 30$ ;IF EQ NO, DON'T TRY TO SCHEDULE BIT T.EFLM(R5),@T.EFLM+2(R5) ;STOPFOR SATISFIED ? BEQ 30$ ;IF EQ NO, DON'T UNSTOP MOV T.ACTL(R5),-(SP) ;REMEMEBER TCB OF NEXT TASK MOV R5,R0 ;COPY TCB ADDRESS BIC #T2.STP*2!T2.STP,T.ST2(R0) ;UNSTOP TASK CALL $EXRQS ;REQUEST TASK TO RUN MOV (SP)+,R5 ;RESTORE NEXT TCB ADDRESS CLR @$RQSCH ;CLEAR POSSIBLE RESCHEDULES BR 5$ ;RESET REGISTERS AND CONTINUE ATL SCAN 29$: CMP #TS.CIP,T.STAT(R5) ;ONLY WAITING FOR CHECKPOINT TO OCCUR? BNE 30$ ;IF NE NO, CAN'T ATTEMPT TO SCHEDULE MOV T.ASTL(R5),R2 ;ANY ASTS QUEUED? BEQ 295$ ;IF EQ, NO MOVB A.CBL(R2),R2 ;ANY KERNEL ASTS? BMI 70$ ;IF MI, YES DON'T DISTURB AST FLAG ASSUME T2.HLT,200 295$: TSTB T.ST2(R5) ;TASK WAITING TO EXIT? BMI 60$ ;IF MI, YES 30$: MOV T.ACTL(R5),R5 ;GET ADDRESS OF NEXT TCB BNE 10$ ;IF NE OKAY 33$: ;REFERENCE LABEL TALLY$ B.IDCT,XA$$ID,CPU ;COUNT AN IDLE LOOP ENTRY .IF DF A$$CNT TSTB $BILNG ;ARE WE BILLING CPU TIME NOW BNE 35$ ;IF NE NO CALL $CPUTM ;TERMINATE BILLING HERE SINCE ;WE PROBABLY WILL GO IDLE, AND 35$: ;DEFINITELY WILL DO A CONTEXT SWITCH .ENDC ; GO VISIT THE IDLE LOOP IN ITS NEW HOME AT THE END OF THIS ; MODULE. THIS KEEPS THE BRANCHES ABOVE FROM BREAKING JMP IDOL ;SORRY ABOUT THE NAME ;I COULDN'T RESIST ; ; WAITFOR SATISFIED-CLEAR WAIT STATE ; .IF DF D$$PAR 50$: MOV KINAR5,-(SP) ;SAVE KERNEL INSTRUCTION APR 5 MOV $DRAPR,KINAR5 ;MAP TO THE DIRECTIVE PARTITION .IFF 50$: ;REFERENCE SYMBOL .IFTF MOV T.PCB(R5),R4 ;GET ADDRESS OF TASK REGION PCB .IF DF X$$HDR MOV P.HDR(R4),-(SP) ;GET VIRTUAL ADDRESS OF HEADER BNE 55$ ;IF NE NOT AN EXTERNAL TASK HEADER MOV P.REL(R4),KISAR6 ;MAP TO EXTERNAL HEADER MOV #140000,(SP) ;SET VIRTUAL ADDRESS OF HEADER 55$: MOV (SP)+,R4 ;GET VIRTUAL ADDRESS OF HEADER .IFF ; DF X$$HDR MOV P.HDR(R4),R4 ;GET TASK HEADER ADDRESS .IFTF MOV T.EFLM+2(R5),R3 ;GET ADDRESS OF EVENT FLAG WORD .ENDC ;DF X$$HDR .IF DF G$$GEF CALL $DEAGF ;DEACCESS GROUP GLOBAL EVENT FLAGS .ENDC ; DF G$$GEF .IFT MOV (SP)+,KINAR5 ;RESTORE MAPPING .ENDC DEC T.ST2(R5) ;CLEAR WAITFOR STATE BMI 60$ ;IF MI TASK IS AT AST STATE BIC #T2.SEF!T2.STP,T.ST2(R5) ;CLEAR STOPFOR STATE ; ; RESTART OR CONTINUE A TASK ; 60$: CLR R4 ;SET FLAG TO SIGNIFY RESTART OF TASK 70$: MOVB T.PRI(R5),@$CURPR ;SET CURRENT TASK PRIORITY .IF DF M$$PRO BIS #TS.RUN,T.STAT(R5) ;SHOW TASK ACTIVE ON CPU .IFTF STCTX: ;REFERENCE LABEL FOR ENTRY FROM THE IDLE ;LOOP 72$: MOV #H.DSW,R0 ;POINT TO DIRECTIVE STATUS WORD MOV $SAHPT,R3 ;GET ADDRESS OF CURRENT TASK HEADER BEQ 80$ ;IF EQ NO CURRENT TASK .IF DF X$$HDR MOV $SAHDB,KISAR6 ;MAP TO HEADER .ENDC ; DF X$$HDR CMP R5,$TKTCB ;NEW TASK SAME AS CURRENT? BNE 73$ ;IF NE NO .IFT MOV $TKTCB,R2 ;GET TCB ADDRESS ASSUME T2.HLT,200 TSTB T.ST2(R2) ;IS TASK HALTED? BMI 73$ ;IF MI YES -- SAVE AND RESTORE CONTEXT .ENDC JMP 130$ ;NO CONTEXT SWITCH NECESSARY ; ; SAVE CONTEXT OF CURRENT TASK ; 73$: ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 04. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH04==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL MOV H.GARD(R3),R2 ;POINT TO HEADER GUARD WORD MOV SP,R1 ;POINT TO SAVED R0 MOV (R1)+,-(R2) ;SAVE R0 MOV (R1)+,-(R2) ;SAVE R1 MOV (R1)+,-(R2) ;SAVE R2 MOV (R1)+,-(R2) ;SAVE R3 MOV (R1)+,-(R2) ;SAVE R4 MOV (R1)+,-(R2) ;SAVE R5 MOV (R1)+,-(R2) ;SAVE PC MOV (R1),-(R2) ;SAVE PS MFPI SP ;GET USER STACK POINTER MOV (SP)+,(R3) ;SAVE USER STACK POINTER IN HEADER 75$: MOV (R0),H.DSW(R3) ;SAVE DIRECTIVE STATUS WORD .IF DF F$$LPP MOV H.FPSA(R3),R2 ;POINT TO FLOATING POINT SAVE AREA BEQ 77$ ;IF EQ TASK DOES NOT USE FLOATING POINT TST $HFMSK ;PROCESSOR HAVE A FPP ? BMI 77$ ;IF MI NO, SKIP CTX STORAGE MOV $TKTCB,R3 ;GET TCB ADDRESS OF CURRENT TASK MOV T.PCB(R3),R1 ;GET ADDRESS OF TASK PARTITION PCB .IF DF X$$HDR TST P.HDR(R1) ;TASK HAVE EXTERNAL HEADER ? BEQ 76$ ;IF EQ YES, NO NEED TO RE-MAP .ENDC ; DF X$$HDR MOV P.REL(R1),KISAR6 ;MAP TO TASK PARTITION .IF DF P$$LAS ADD T.OFF(R3),KISAR6 ;ADD IN OFFSET TO TASK IMAGE .ENDC 76$: ;REF LABEL STFPS (R2)+ ;SAVE FLOATING POINT STATUS SETD ;SET FLOATING DOUBLE MODE STD R0,(R2)+ ;SAVE FLOATING POINT REGISTERS LDD R4,R0 ; STD R0,(R2)+ ; LDD R5,R0 ; STD R0,(R2)+ ; STD R1,(R2)+ ; STD R2,(R2)+ ; STD R3,(R2)+ ; .ENDC 77$: ; .IF DF A$$CNT TSTB $BILNG ;ARE WE BILLING CPU TIME NOW BNE 80$ ;IF NE NO CALL $CPUTM ;ADD TIME USED TO USER ACCOUNTING MOV #H.DSW,R0 ;RESTORE DIRECTIVE STATUS WORD TO R0 .ENDC ; ; LOAD CONTEXT OF NEW TASK ; 80$: MOV R5,$TKTCB ;SET ADDRESS OF NEW TCB .IF DF M$$PRO .IF DF X$$HDR CLR $SAHPT ;CLEAR HEADER PTR IN CASE $TKTCB = 0 .IFF CLR $HEADR ;CLEAR HEADER .ENDC MOV R5,@$TKPTR ;SET NEW TCB ADDRESS IN TABLE BNE 81$ ;IF NE CURRENT TASK EXISTS JMP IDLE1 ;RE-ENTER IDLE LOOP 81$: BIT #T2.ABO!T2.HLT,T.ST2(R5) ;TASK MARKED FOR ABORT? BNE 82$ ;IF NE YES MOVB $PROCN,T.CPU(R5) ;SAVE PROCESSOR NUMBER IN TCB 82$: ;REF SYMBOL .ENDC TALLY$ B.CTXP,XA$$CX,CPU ;COUNT A CONTEXT SWITCH .IF DF A$$CNT MOV KISAR6,-(SP) ;SAVE MAPPING MOV T.ACN(R5),KISAR6 ;MAP ACCOUNTING BLOCK BEQ 825$ ;IF EQ, NO ACCOUNTING CMPB #BT.TAB,@#B.TYP+140000 ;IS THIS A TAB BNE 825$ ;IF NE NO ADD #1,@#B.CTXT+2+140000 ;COUNT IT ADC @#B.CTXT+140000 ; 825$: MOV (SP)+,KISAR6 ;RESTORE .ENDC ;A$$CNT .IF DF D$$MND TST $DITCB ;IS DIAMOND WATCHING A TASK? BEQ 83$ ;IF EQ NO BIC #1,@$DICSR ;ASSUME NOT WATCHING CURRENT TASK CMP $TKTCB,$DITCB ;IS DIAMOND WATCHING CURRENT TASK? BNE 83$ ;IF NE NO BIS #1,@$DICSR ;SET DIAMOND REGISTER 83$: ;REFERENCE SYMBOL .ENDC .IF DF S$$LIB MOV #PMODE,PS ;INSURE PREVIOUS MODE IS USER .ENDC MOV T.PCB(R5),R3 ;GET ADDRESS OF TASK PARTITION PCB MOV P.HDR(R3),R2 ;GET ADDRESS OF TASK HEADER .IF DF X$$HDR BNE 84$ ;IF NE HEADER IS RESIDENT MOV #$SAVSP,$HEADR ;POINT TO STACK POINTER SAVE AREA MOV #140000,R2 ;POINT TO START OF NON-RESIDENT HEADER MOV P.REL(R3),KISAR6 ;MAP TO NON-RESIDENT HEADER MOV P.REL(R3),$SAHDB ;REMEMBER TASK HEADER MAPPING BIAS BR 841$ ;AND JOIN COMMON CODE 84$: MOV R2,$HEADR ;POINT TO HEADER SAVED STACK POINTER .ENDC ; DF X$$HDR 841$: MOV R2,$SAHPT ;SAVE ADDRESS OF TASK HEADER .IF DF F$$MAP&X$$HDR&P$$LAS MOV H.FMAP(R2),$FMAPP ;LOAD FAST MAP CONTEXT POINTER .ENDC ; DF F$$MAP&X$$HDR&P$$LAS MOV R4,-(SP) ;SAVE EFFECT AST FLAG MOV H.WND(R2),R4 ;POINT TO NUMBER OF WINDOW BLOCKS TST W.BLVR+2(R4) ;IS TASK MAPPED TO THE EXEC? BEQ 85$ ;IF EQ NO MOV R2,R1 ;COPY ADDRESS OF TASK HEADER ADD R0,R1 ;POINT TO DIRECTIVE STATUS WORD MOV (R1)+,(R0)+ ;RESTORE DIRECTIVE STATUS WORD MOV (R1)+,(R0)+ ;RESTORE POINTER TO FCS IMPURE AREA MOV (R1)+,(R0)+ ;RESTORE POINTER TO FORTRAN IMPURE AREA MOV (R1)+,(R0)+ ;RESTORE POINTER TO OVERLAY IMPURE AREA MOV (R1)+,(R0)+ ;RESTORE PTR TO VECTOR OF IMPURE PTRS MOV #UINDR0,R0 ;POINT TO USER I DESCRIPTOR REG 0 .IF DF K$$DAS!M$$PRO .IF DF I$$CBP MOV #<<<<$ICTOP+77>*4>-400>&77400>!6,(R0)+ ;MIN SIZE NEEDED .IFF ;DF,I$$CBP MOV #<<<<$UTEND+77>*4>-400>&77400>!6,(R0)+ ;MIN SIZE NEEDED .ENDC ;DF,I$$CBP .IFTF .IF DF M$$PRO MOV #177406,(R0) ;SETUP PRIV TASK PDR FOR 4K BYPASSED .IFF MOV #77406,(R0) ;SETUP PRIVILEGED TASK DESCRIPTOR REGISTERS .ENDC .IFF MOV (R0)+,(R0) ; .ENDC MOV (R0),UINDR0+14. ;ALLOW FULL ACCESS TO I/O PAGE ;+ ; If the task is installed, with T4.RON set, then pool will be protected ; from accidental harm when the privileged task is in user mode. Note that ; APR0 must be mapped R/W, since the system will attempt to store directive ; status in $DSW, which is in LOWCR. ;- BIT #T4.RON,T.ST4(R5) ; TASK SET FOR R/O EXECUTIVE ACCESS BEQ 842$ ; IF EQ, NOPE, LEAVE R/W ACCESS TO POOL BIC #4,(R0) ; FORCE ACCESS TO R/O 842$: MOV (R0)+,(R0) ; MOV (R0)+,(R0) ; MOV (R0)+,(R0) ; MOV #UINAR0,R1 ;POINT TO USER I ADDRESS REG 0 MOV #KISAR0,R0 ;POINT TO KERNAL ADDRESS REGISTER 0 MOV (R0)+,(R1)+ ;SETUP PRIVILEGED TASK ADDRESS REGISTERS MOV (R0)+,(R1)+ ; MOV (R0)+,(R1)+ ; MOV (R0)+,(R1)+ ; MOV (R0),(R1) ; MOV #177600,UINAR0+14. ;SET ADDRESS REG 7 FOR I/O PAGE BR 90$ ; 85$: MOV #UINDR0,R0 ;POINT TO USER I DESCRIPTOR REG 0 86$: CLR (R0)+ ;CLEAR ALL DESCRIPTOR REGISTERS CLR (R0)+ ; CLR (R0)+ ; CLR (R0)+ ; CLR (R0)+ ; CLR (R0)+ ; CLR (R0)+ ; CLR (R0) ; 90$: ;REFERENCE LABEL .IF DF S$$LIB BIC #10,SR3 ;ASSUME NEXT TASK DOESN'T USE SUPER ;MODE (DISABLE CSM INSTRUCTION) TSTB $SIRWF ;SUPERVISOR MODE R/W PDR'S? BEQ 95$ ;IF EQ NO CLRB $SIRWF ;CLEAR FLAG MOV #SISDR0,R0 ;POINT TO FIRST SUPER I SPACE PDR BR 86$ ;CLEAR SUPER I SPACE PDR'S 95$: MOVB #-1,$SUPFL ;INDICATE NO SUPERVISOR WINDOWS .ENDC MOV (R4)+,-(SP) ;PUSH NUMBER OF WINDOW BLOCKS 100$: ADD #W.BLGH,R4 ;POINT PAST CURRENT WINDOW BLOCK MOV -W.BLGH(R4),R3 ;PICK UP NEXT PCB ADDRESS BEQ 115$ ;IF EQ WINDOW IS NOT MAPPED CMP -(R4),-(R4) ;POINT TO FIRST PDR ADDRESS MOV P.REL(R3),R0 ;PICK UP PARTITION RELOCATION BIAS .IF DF P$$LAS ADD -2(R4),R0 ;ADD IN WINDOW OFFSET .ENDC MOVB (R4)+,R1 ;POINT TO FIRST PDR .IF DF S$$LIB BMI 105$ ;IF MI USER MODE WINDOW INCB $SUPFL ;COUNT A SUPERVISOR MODE WINDOW BNE 102$ ;IF NE THIS ISN'T THE FIRST MOV $DRAP3,SISAR0 ;FORCE MAPPING TO DISPATCHER IN EXEC ;IN CASE TASK HAS NO SUPER MODE 0 WINDOW MOV #402,SISDR0 ;MAP 1 32WD BLOCK RO 102$: ADD #SISDR0,R1 ;POINT TO FIRST SUPER INSTRUCTION PDR BIT #4,W.BLPD-W.BNPD(R4) ;R/W ACCESS TO SUPER I SPACE? BEQ 105$ ;IF EQ NO INCB $SIRWF ;SET FLAG FOR SUPER I SPACE WRITE ACCESS .ENDC 105$: MOVB (R4)+,R3 ;PICK UP NUMBER OF PDR'S TO LOAD 110$: MOVB (R4),(R1)+ ;SET USER DESCRIPTOR ACCESS CODE MOVB #177,(R1)+ ;SET BLOCK LENGTH .IF DF M$$PRO!C$$CBP BIT #WB.BPS,(R4) ;ALWAYS BYPASS? BEQ 111$ ;NO IF EQ BISB #200,-1(R1) ;SET UP TO ALWAYS BYPASS CACHE BR 112$ ; 111$: BIT #WB.NBP,(R4) ;CACHE BYPASS NOT DESIRED FOR THIS WINDOW? BNE 112$ ;YES IF NE, DO NOT BYPASS CACHE BISB 1(R4),-1(R1) ;SET BYPASS BIT IN PDR AS APPROPRIATE .ENDC ; DF M$$PRO!C$$CBP 112$: MOV R0,UISAR0-UISDR0-2(R1) ;LOAD USER ADDRESS REGISTER ADD #200,R0 ;ADVANCE TO NEXT 4K BOUNDARY DEC R3 ;ANY MORE TO LOAD? BGT 110$ ;IF GT NO MOV (R4)+,-(R1) ;LOAD LAST USER DESCRIPTOR REGISTER .IF DF M$$PRO!C$$CBP BIT #WB.BPS,-2(R4) ;ALWAYS BYPASS? BEQ 113$ ;IF EQ NO BIS #100000,(R1) ;SET UP TO ALWAYS BYPASS CACHE BR 115$ ; 113$: BIT #WB.NBP,-2(R4) ;CACHE BYPASS NOT DESIRED FOR THIS WINDOW? BEQ 115$ ;NO IF EQ, BYPASS CACHE AS APPROPRIATE BIC #100000,(R1) ;DO NOT BYPASS CACHE .ENDC ; DF M$$PRO!C$$CBP 115$: DEC (SP) ;ANY MORE WINDOW BLOCKS? BGT 100$ ;IF GT YES .IF DF S$$LIB INCB $SUPFL ;ADJUST SUPER MODE WINDOW COUNT .ENDC ; DF S$$LIB MOV (R2),(SP) ;LOAD USER STACK POINTER MTPI SP ; MOV #$UMR4,(R2) ;POINT SAVED SP VALUE AT SAVED R4 ; IF A USER D SYSTEM, UPDATE THE USER D PAR'S/PDR'S TO OVERMAP ; USER I SPACE WHERE APPROPRIATE. .IF DF U$$DAS MOV R2,-(SP) ;SAVE TASK HEADER ADDRESS FOR LATER MOV #UINAR7+2,R0 ;POINT PAST USER I PAR 7 MOV #UINDR7+2,R1 ;POINT PAST USER I PDR 7 MOV #UDSAR7+2,R3 ;POINT PAST USER D PAR 7 MOV #UDSDR7+2,R4 ;POINT PAST USER D PDR 7 MOVB H.DMAP(R2),R2 ;GET USER D SPACE MAPPING MASK BNE 118$ ;IF NE MAPPING IS MIXED ; NONE OF USER D HAS DISCRETE MAPPING. COPY ALL REGISTERS ; FROM USER I MOV -(R0),-(R3) ;PAR 7 MOV -(R1),-(R4) ;PDR 7 MOV -(R0),-(R3) ;6 MOV -(R1),-(R4) ; MOV -(R0),-(R3) ;5 MOV -(R1),-(R4) ; MOV -(R0),-(R3) ;4 MOV -(R1),-(R4) ; MOV -(R0),-(R3) ;3 MOV -(R1),-(R4) ; MOV -(R0),-(R3) ;2 MOV -(R1),-(R4) ; MOV -(R0),-(R3) ;1 MOV -(R1),-(R4) ; MOV -(R0),-(R3) ;0 MOV -(R1),-(R4) ; BR 119$ ;SKIP MIXED UPDATE CODE ; USER D SPACE MAPPING IS A MIXTURE (OR ALL D SPACE). TEST FOR ; LATTER CASE, THEN UPDATE AS APPROPRIATE. 118$: COMB R2 ;REVERSE SENSE OF BIT MASK ;(1 NOW MEANS APR IS MAPPED TO I SPACE) BEQ 119$ ;IF EQ, ALL APRS MAPPED BY DISCRETE ;D SPACE WINDOWS, NO UPDATE NEEDED. BMI 1182$ ;IF MI, APR 7 IS MAPPED TO USER I ; THIS SECTION HANDLES APRS WITH DISCRETE MAPPING 1181$: CMP -(R0),-(R3) ;ADVANCE PAR ADDRESSES CMP -(R1),-(R4) ;ADVANCE PDR ADDRESSES ASLB R2 ;TEST FOR NEXT APR BEQ 119$ ;IF EQ END OF LOOP OR ALL REMAINING ;APRS HAVE DISCRETE MAPPING BPL 1181$ ;IF PL NEXT APR HAS DISCRETE MAPPING, ;BUT AT LEAST ONE MORE DOES NOT. ; THIS SECTION HANDLES APRS MAPPED TO USER I SPACE 1182$: MOV -(R0),-(R3) ;COPY USER I PAR TO USER D PAR MOV -(R1),-(R4) ;COPY USER I PDR TO USER D PDR ASLB R2 ;TEST FOR NEXT APR BMI 1182$ ;NEXT APR MAPS USER I SPACE BNE 1181$ ;IF NE, NEXT APR IS NOT OVERMAPPED, ;BUT AT LEAST ONE MORE IS 119$: MOV (SP)+,R2 ;RESTORE TASK HEADER ADDRESS .ENDC ; DF U$$DAS MOV (SP)+,R4 ;RESTORE EFFECT AST INDICATOR .IF DF F$$LPP MOV H.FPSA(R2),R0 ;POINT TO FLOATING POINT SAVE AREA BEQ 120$ ;IF EQ TASK DOES NOT USE FLOATING POINT TST $HFMSK ;PROCESSOR HAVE A FLOATING PT UNIT ? BMI 120$ ;IF MI NO, DON'T TRY TO LOAD CTX MOV T.PCB(R5),R1 ;GET ADDRESS OF TCB OF NEXT TASK MOV P.REL(R1),KISAR6 ;MAP TO TASK PARTITION .IF DF X$$HDR TST P.HDR(R1) ;TASK HAVE EXTERNAL HEADER ? BEQ 121$ ;IF EQ, YES .IFTF ;DF X$$HDR .IF DF P$$LAS ADD T.OFF(R5),KISAR6 ;ADD IN OFFSET TO TASK IMAGE .ENDC .IFT ;DF X$$HDR 121$: ;REFERENCE LABEL .ENDC ;DF X$$HDR TST (R0)+ ;POINT TO SAVED FLOATING POINT REGISTERS LDFPS #200 ;SET FLOATING DOUBLE MODE, NO TRAPS LDD (R0)+,R0 ;RESTORE FLOATING POINT REGISTERS LDD (R0)+,R1 ; STD R1,R4 ; LDD (R0)+,R1 ; STD R1,R5 ; LDD (R0)+,R1 ; LDD (R0)+,R2 ; LDD (R0)+,R3 ; LDFPS @H.FPSA(R2) ;RESTORE FLOATING POINT STATUS .ENDC 120$: ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 05. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH05==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL MOV H.GARD(R2),R0 ;POINT TO HEADER GUARD WORD MOV SP,R1 ;POINT TO CURRENT CONTEXT MOV -(R0),(R1)+ ;RESTORE R0 MOV -(R0),(R1)+ ;RESTORE R1 MOV -(R0),(R1)+ ;RESTORE R2 MOV -(R0),(R1)+ ;RESTORE R3 MOV -(R0),(R1)+ ;RESTORE R4 MOV -(R0),(R1)+ ;RESTORE R5 MOV -(R0),(R1)+ ;RESTORE PC MOV -(R0),(R1) ;RESTORE PS 130$: .IF DF A$$CNT TST T.ACN(R5) ;DOES TASK HAVE AN ACCOUNTING BLOCK BEQ 132$ ;IF EQ NO TSTB $BILNG ;IS BILLING CURRENTLY ACTIVE BEQ 132$ ;IF EQ YES MOV $ACCLK+2,$STRTM+2 ;SAVE CURRENT ABSOLUTE TIME MOV $ACCLK,$STRTM ; CLRB $BILNG ;INDICATE START OF BILLING .ENDC ; A FEW DESCRIPTIVE WORDS ABOUT AST CONTROL BLOCKS ; ; AST CONTROL BLOCKS FALL INTO SEVERAL DISTINCT CATEGORIES BASED ; UPON THE VALUES IN A.CBL AND A.BYT. THESE ARE ; ; A.CBL A.BYT DESCRIPTION ; ----- ----- ----------- ; ; <0 X KERNEL AST. BIT 6 OF A.CBL IS SET IF $SGFIN ; SHOULD NOT BE CALLED PRIOR TO EXECUTING THE ; KERNEL AST CODE. BITS 0 THROUGH 5 OF A.CBL ; REPRESENT AN INDEX (DIVIDED BY 2) INTO A ; TABLE OF AST ADDRESSES ($KATBL). DEALLOCATION ; IS THE RESPONSIBILITY OF THE PROCESSING ROUTINE. ; THESE ARE EXEC LEVEL FUNCTIONS SUCH AS BUFFERED ; I/O COMPLETION WHICH MUST TAKE PLACE WHEN THE ; TASK CONTEXT IS LOADED. ; ; 0 0 AST DEQUEUED BY A SYSTEM SUBROUTINE. THE ROUTINE ; IS MAPPED BY THE CONTENTS OF A.KSR5 AND CALLED ; VIA THE ADDRESS IN A.DQSR. DEALLOCATION IS THE ; RESPONSIBILITY OF THE DEQUEUE ROUTINE. AN ; EXAMPLE IS THE PROCESSING OF UNSOLICITED INPUT ; ASTS BY THE FULL DUPLEX TTDRV. ; ; 0 N THIS IS A SPECIFIED AST BLOCK OF LENGTH C.LGTH ; (A.PLGH FOR PARITY ERROR ASTS) N IS THE SPECIFIED ; AST TYPE. THESE BLOCKS ARE RE-LINKED IN THE ; T.SAST LIST AFTER THE AST IS DECLARED (EXCEPT FOR) ; PARITY ERROR ASTS, WHICH ARE ALWAYS DEALLOCATED ; AFTER USE, AND REQUESTED EXIT ASTS, WHICH ARE ; DEALLOCATED AFTER USE BY A NON-PRIVILEGED TASK. ; ; >0 0 THIS IS A DYNAMIC AST (I/O COMPLETION, MARK TIME ; OF LENGTH A.CBL. AFTER THE PARAMETERS ARE MOVED ; TO THE TASK STACK AND THE AST EFFECTED THE BLOCK ; IS DEALLOCATED. ; 132$: TST R4 ;EFFECT AST? BNE TAST ;IF NE YES JMP 190$ ;NO TAST: MOV R5,R0 ;CALCULATE ADDRESS OF AST LISTHEAD ADD #T.ASTL,R0 ; CALL $QRMVF ;REMOVE AST ENTRY FROM QUEUE MOVB A.CBL(R1),R4 ;KERNEL AST ? BPL 135$ ;IF PL NO JMP 210$ ; 135$: MOV R5,R4 ;CALCULATE ADDRESS OF STATUS WORD ADD #T.ST2,R4 ; MOVB (R4),-(SP) ;COPY CURRENT EXTENSION BYTE BIC #^C,(SP) ;CLEAR ALL BUT WAIT STATE ASL (SP) ;SHIFT INTO POSITITON FOR SAVE BIC #*2!T2.STP!T2.SPN!T2.WFR,(R4) ; BIS (SP)+,(R4) ;SAVE WAIT STATE BIS #T2.AST,(R4) ;SET AST IN PROGRESS MOV R1,R3 ;COPY AST CONTROL BLOCK ADDRESS MOV R3,-(SP) ;SAVE AST CONTROL BLOCK ADDRESS CMP (R3)+,(R3)+ ;POINT TO NUMBER OF BYTES TO ALLOCATE .IF DF X$$HDR MOV $SAHPT,R4 ;POINT TO CURRENT TASK HEADER .IFF MOV $HEADR,R4 ;POINT TO CURRENT TASK HEADER .ENDC ;X$$HDR MFPI SP ;GET CURRENT STACK POINTER MOV (SP)+,R0 ; MOV (R3)+,R1 ;GET NUMBER OF BYTES TO ALLOCATE ON TASK SUB R1,R0 ;CALCULATE NEW TOP OF STACK CALL $ACHCK ;ADDRESS CHECK STACK SPACE BCS 160$ ;IS CS ADDRESS CHECK FAILURE .IF DF S$$LIB MOV #PMODE,PS ;SET PREVIOUS MODE TO USER .IFTF .IF DF X$$HDR MOV KISAR6,-(SP) ;SAVE TASK HEADER MAPPING IF XTRNL HEADER .IFTF ; DF X$$HDR MOV R0,-(SP) ;SET NEW TASK STACK POINTER MTPI SP ; CALL $RELOM ;RELOCATE AND MAP STACK ADDRESS MOV SP,R1 ;CALCULATE ADDRESS OF TRAP PC .IFF ; DF X$$HDR ADD #7*2,R1 ; .IFT ; DF X$$HDR ADD #8.*2,R1 ; .ENDC ; DF X$$HDR MOV (R1)+,-(SP) ;SAVE PC AT TRAP MOV (R1),R2 ;SAVE PS AT TRAP MOV #CMODE!PMODE,(R1) ;SET AST TRAP PS MOV (R3)+,-(R1) ;SET AST TRAP PC MOV (R3)+,-(SP) ;GET NUMBER OF PARAMETERS TO MOVE .IFT BIT #1,(R1) ;SUPERVISOR MODE AST? BEQ 140$ ;IF EQ NO DEC (R1)+ ;CLEAR SUPERVISOR FLAG TSTB $SUPFL ;TASK HAVE SUPER MODE LINKAGE ? BEQ 140$ ;IF EQ NO, DON'T ALLOW SUPER AST BIC #^CCSMODE&CMODE,(R1) ;SET SUPERVISOR MODE IN STACK PS .ENDC 140$: DEC (SP) ;ANY MORE PARAMETERS TO MOVE? BLT 150$ ;IF LT NO MOV (R3)+,(R0)+ ;MOVE PARAMETER TO USER STACK BR 140$ ; 150$: TST (SP)+ ;CLEAN STACK MFPD$ @#H.DSW ;GET USER DSW MOV (SP)+,(R0)+ ;MOVE DSW TO TASK STACK MOV (SP)+,(R0)+ ;MOVE PC AT TRAP TO TASK STACK MOV R2,(R0)+ ;MOVE PS AT TRAP TO TASK STACK MOV T.EFLM(R5),(R0) ;SAVE WAITFOR MASK WORD .IF DF X$$HDR MOV (SP)+,KISAR6 ;RESTORE MAPPING TO XTRNL TASK HEADER .ENDC MOV T.EFLM+2(R5),H.EFSV(R4) ;SAVE WAITFOR MASK ADDRESS BR 170$ ;TAKE COMMON EXIT 160$: MOV #S.CAST,R0 ;SET AST ABORT CALL $ABCTK ;ABORT CURRENT TASK 170$: MOV (SP)+,R0 ;RETRIEVE AST CONTROL BLOCK ADDRESS MOV A.CBL(R0),R1 ;GET LENGTH OF BLOCK TO RELEASE BNE 175$ ;JUMP IF NON-ZERO CMP -(R0),-(R0) ;ZERO - POINT TO A.KSR5 .IF DF K$$DAS MOV (R0),KDSAR5 ;MAP DEQUEUE ROUTINE IN DATA SPACE .ENDC MOV (R0)+,KINAR5 ;MAP DEQUEUE ROUTINE IN INSTR SPACE CALL @(R0)+ ;CALL DEQUEUE SUBROUTINE BR 200$ ;EXIT 175$: TSTB R1 ;LENGTH NON-ZERO? BNE 180$ ;Y - JUMP SWAB R1 ;GET AST CODE CMPB R1,#AS.PEA ;PARITY ERROR AST BLOCK? BEQ 1781$ ;IF EQ YES, DEALLOCATE IT .IF DF A$$CLI CMPB R1,#AS.CAA ;COMMAND ARRIVAL AST BLOCK BNE 176$ ;IF NE NO TST A.PRM+2(R0) ;SHOULD AST BLOCK BE DEALLOCATED? BEQ 177$ ;IF EQ YES BR 178$ ;RELINK BLOCK 176$: ; .ENDC ;A$$CLI CMPB R1,#AS.REA ;REQUESTED EXIT AST BLOCK? BNE 179$ ;IF NE NO BIT #T3.PRV,T.ST3(R5) ;TASK PRIVILEGED? BNE 178$ ;IF NE YES 177$: CALL $DECLK ;DEALLOCATE AST CONTROL BLOCK BR 200$ ; 178$: BIC #T2.REX,T.ST2(R5) ;ALLOW AST RESPECIFICATION 179$: MOV T.SAST(R5),(R0) ;LINK AST CONTROL BLOCK BACK INTO MOV R0,T.SAST(R5) ;THE HEAD OF THE LIST BR 200$ ;TRY EXIT AGAIN 1781$: MOV #A.PLGH,R1 ;GET LENGTH OF PACKET 180$: CALL $DEACB ;DEALLOCATE CONTROL BLOCK BR 200$ ;TRY EXIT AGAIN 190$: TSTB T.ST2(R5) ;TASK BEING HALTED? BPL 200$ ;IF PL NO TEXIT: ;REFERENCE LABEL .IF DF X$$HDR MOV $SAHDB,KISAR6 ;MAP CURRENT TASK HEADER .ENDC ; DF X$$HDR CALL $DREX1 ;CONTINUE TASK EXIT PROCESS 200$: ;REF LABEL .IF DF S$$LIB TSTB $SUPFL ;DOES TASK HAVE SUPERVISOR WINDOWS? BEQ 205$ ;IF EQ NO CALL LSUPD1 ;LOAD SUPERVISOR DATA REGISTERS TST $STACK-2 ;GOING TO SUPERVISOR MODE? BMI 205$ ;IF MI NO MFPI SP ;GET CURRENT STACK POINTER MOV (SP),-(SP) ;MAKE A COPY ON THE STACK ADD #4,(SP) ;MAKE USER SP 4 MORE THAN SUPER SP MOV #PMODE,PS ;SET PREVIOUS MODE TO USER MTPI SP ;LOAD USER STACK POINTER BIC #^CPSMODE&PMODE,PS ;SET PREVIOUS MODE TO SUPERVISOR MTPI SP ;LOAD SUPERVISOR STACK POINTER .ENDC .IF NDF M$$PRO 205$: JMP $DIRXT ; .IFF 205$: JMP DIRXT1 ; .ENDC 210$: MOV #$DIRXT,-(SP) ;SET RETURN ADDRESS MOV R1,R0 ;SET ADDRESS OF AST CONTROL BLOCK CLR (R0) ;INDICATE THIS IS A SCHEDULER CALL 211$: ASLB R4 ;CONVERT AST INDEX TO WORD, TST $SGFIN BMI 215$ ;IF MI NO $SGFIN REQUIRED CALL $SGFIN ;SETUP TO IGNORE SEGMENT FAULTS .IF DF R$$WPT MOV $KATBL+256.(R4),$WPLST ;SAVE LAST SYSTEM STATE ADDRESS .ENDC ; DF R$$WPT JMP @$KATBL+256.(R4) ;DISPATCH TO PROPER ROUTINE 215$: .IF DF R$$WPT MOV $KATBL+128.(R4),$WPLST ;SAVE LAST SYSTEM STATE ADDRESS .ENDC ; DF R$$WPT JMP @$KATBL+128.(R4) ;DISPATCH TO PROPER ROUTINE ;+ ;**-$DSPKA-DISPATCH KERNEL AST ; ; THIS ROUTINE IS CALLED WHEN A KERNEL AST IS TO BE DISPATCHED ; BY A COMPONENT OTHER THAN THE SCHEDULER (SPECIFICALLY THE ; LOADER TO DISPATCH REGION LOAD ASTS. ; ; INPUTS: ; R0=ADDRESS OF KERNEL AST BLOCK ; ; OUTPUTS: ; THE AST IS SERVICED ; ; NOTE: THE TASK CONTEXT IS NOT GUARANTEED LOADED, SO THE AST ; MAY ONLY BE USED TO PERFORM SERVICES DEPENDENT UPON CONDITIONS ; GUARANTEED BY THE CALLER OF THIS ROUTINE. ;- $DSPKA::MOV KINAR5,-(SP) ;SAVE CURRRENT APR 5 MAPPING .IF DF K$$DAS MOV KDSAR5,-(SP) ;SAVE D SPACE MAPPING .ENDC ; DF K$$DAS MOVB A.CBL(R0),R4 ;GET CAUSE OF AST MOV #1,(R0) ;SET LINK NON-ZERO TO INDICATE ;NOT A SCHEDULER REQUEST CALL 211$ ;GO EXECUTE AST .IF DF K$$DAS MOV (SP)+,KDSAR5 ;RESTORE PREVIOUS D MAPPING .ENDC ; DF K$$DAS MOV (SP)+,KINAR5 ;RESTORE PREVIOUS MAPPING RETURN ; .DSABL LSB ;+ ; **-$GGFRN-GROUP GLOBAL EVENT FLAG USE COUNT RUNDOWN ; ; DEACCESS THIS TASK'S GROUP GLOBAL EVENT FLAGS IF THE EVENT FLAG ; MASK IN THE AST CONTROL BLOCK IS GROUP GLOBAL, AND DEALLOCATE THE ; THE AST CONTROL BLOCK. ; ; INPUTS: ; ; R0=ADDRESS OF THE KERNEL AST CONTROL BLOCK ; ; TASK HEADER IS EITHER RESIDENT OR MAPPED THROUGH KISAR6 ; AND $SAHPT IS ASSUMED TO BE VALID AT THIS POINT. ; ; OUTPUTS: ; ; THE GROUP GLOBAL EVENT FLAGS ARE DEACCESSED AND ; THE CONTROL BLOCK IS DEALLOCATED. ; ; FORMAT OF THE AST CONTROL BLOCK: ; ; WD. 00 -- UNKNOWN ; WD. 01 -- KERNEL AST TYP = AK.GGF ; WD. 02 -- UNKNOWN ; WD. 03 -- EVENT FLAG MASK ADDRESS ; ;- .IF DF G$$GEF $GGFRN::MOV $SAHPT,R4 ;GET CURRENT TASK'S HEADER ADDRESS MOV R0,-(SP) ;SAVE CONTROL BLOCK ADDRESS MOV 6(R0),R3 ;GET EVENT FLAG MASK ADDRESS CALL $DEAGF ;DEACCESS IF GROUP GLOBAL MOV (SP)+,R0 ;RESTORE CONTROL BLOCK ADDRESS CALL $DEPKT ;DEALLOCATE THE CONTROL BLOCK CALLR $SETRT ;INSURE RESCAN OF TASK .ENDC ; DF G$$GEF .IF DF P$$OFF ;+ ; **-$FINXT-FINISH OFFSPRING TASK EXIT PROCESSING ; ; THIS ROUTINE IS CALLED TO OPTIONALLY SET AN EVENT FLAG, DECLARE AN ; AST AND RETURN EXIT STATUS TO A PARENT TASK ONCE THAT TASK HAS BEEN ; SCHEDULED. ; ; INPUTS: ; ; R0=ADDRESS OF OFFSPRING CONTROL BLOCK. ; ; OUTPUTS: ; ; ALL EXIT CONDITIONS ARE EFFECTED AND THE OFFSPRING CONTROL BLOCK ; IS DEALLOCATED IF IT IS NOT USED AS AN AST CONTROL BLOCK. ;- $FINXT::MOV R0,R3 ;COPY OCB POINTER MOV R0,R4 ;COPY OCB POINTER TST (R3)+ ;SKIP OVER LINK WORD (O.LNK) MOV #O.LGTH,(R3)+ ;SET LENGTH TO DEALLOCATE (O.LNK=A.CBL) MOV (R3),R5 ;PICK UP PARENT TCB ADDR (O.PTCB=A.BYT) MOV #8.*2,(R3)+ ;BYTES ON USER STACK (O.PTCB=A.BYT) TST (R3)+ ;SKIP OVER AST WORD (O.AST=A.AST) MOV (R3),R0 ;PICK UP EFN NUMBER (O.EFN=A.NPR) CALL $SETFG ;SET EFN AND UNLOCK IF GRP GLOBAL MOV #1,(R3)+ ;SET NUMBER OF AST PARMS (O.EFN=A.NPR) MOV (R3)+,R0 ;PICK UP VIRTUAL ESB ADDR (O.ESB=A.PRM) MOV #1,R2 ;ASSUME ONE WORD STATUS BLOCK ASR R0 ;ONE WORD STATUS BLOCK ? BEQ 40$ ;IF EQ NO STATUS BLOCK SPECIFIED BCC 5$ ;IF CC ONE WORD STATUS BLOCK MOV #8.,R2 ;SET SIZE TO EIGHT WORDS 5$: ASL R0 ;SET ADDRESS BACK TO ORIGINAL CLC ;MAKE SURE CARRY IS CLEAR TO DETECT MTPD$ TRAP MOV R0,-2(R3) ;CORRECT ADDRESS IN AST BLOCK FOR STACK 10$: MOV (R3)+,-(SP) ;GET A WORD OF THE ESB MTPD$ (R0)+ ;STORE IN USER BUFFER (CAN TRAP) BCS 40$ ;IF CS TRAPPED, NO POINT CONTINUING SOB R2,10$ ;CONTINUE WITH COPY 40$: TST O.AST(R4) ;EFFECT AST? BEQ 50$ ;IF EQ NO MOV R5,R0 ;SET PARENT TCB ADDRESS MOV R4,R1 ;SET AST BLOCK ADDRESS CALLR $QASTT ;QUEUE AST FOR PARENT AND RETURN 50$: MOV R4,R0 ;POINT TO BLOCK TO RELEASE MOV #O.LGTH,R1 ;PICK UP SIZE TO RELEASE CALL $DEACB ;DEALLOCATE OCB CALLR $SETRT ;INSURE RESCAN OF TASK .IFF ;DF P$$OFF $FINXT::BGCK$A BF.KAS,BE.SGN,FATAL ;SHOULDN'T HAVE AK.OCB IN NON P$$OFF SYSTEM .ENDC ;+ ; **-$DBTRP-SET T BIT IN SAVED PS TO CAUSE TASK TO TRAP INTO DEBUGGER ; ; THIS LOCAL ROUTINE IS CALLED AS A KERNEL AST TO FORCE A TASK ; TO TRAP INTO A DEBUGER. IT IS CALLED AS A RESULT OF THE MCR ; "DEBUG" COMMAND QUEUEING THE KERNEL AST BLOCK ; ; INPUTS: ; ; R0=ADDRESS OF KERNEL AST BLOCK ; R5=ADDRESS OF TCB OF CURRENT TASK ; ; OUTPUTS: ; ; THE "T" BIT IS SET IN THE SAVED PS IN THE TASK'S HEADER TO CAUSE ; ITTO TRAP. THE AST BLOCK IS DEALLOCATED. IF THE TASK DOES NOT HAVE ; A DEBUGGER SST VECTOR SPECIFIED, OR IS EXITING, THE T BIT IS NOT ; SET, AND THE AST BLOCK IS USED TO QUEUE A MESSAGE REQUEST TO ; TKTN FOR OUTPUT. ; ;- $DBTRP::BIT #T2.ABO!T2.HLT,T.ST2(R5) ;IS TASK EXITING OR ABORTING BNE 20$ ;IF NE YES MOV T.PCB(R5),R4 ;FIND TASK'S PCB .IF DF X$$HDR MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING IN CASE XTRNL HDR MOV P.HDR(R4),-(SP) ;POINT TO TASK HEADER BNE 5$ ;IF NE RESIDENT HEADER MOV P.REL(R4),KISAR6 ;MAP TO EXTERNAL HEADER MOV #140000,(SP) ;POINT TO VIRTUAL ADDRESS OF HEADER 5$: MOV (SP)+,R4 ;GET VIRTUAL ADDRESS OF HEADER MOV H.ODVA(R4),R4 ;GET VECTOR ADDRESS MOV (SP)+,KISAR6 ;RESTORE CURRENT MAPPING TST R4 ;IS A DEBUGGER SST SPECIFIED .IFF ; DF X$$HDR MOV P.HDR(R4),R4 ;POINT TO HEADER TST H.ODVA(R4) ;IS A DEBUGGER SST SPECIFIED .ENDC ; DF X$$HDR BEQ 20$ ;IF EQ NO BIC #T2.SEF!T2.STP!T2.SPN!T2.WFR,T.ST2(R5) ;MAKE TASK RUNNABLE BIS #20,@#$STACK-2 ;SET T BIT IN SAVED PS 10$: MOV #A.DLGH,R1 ;LENGTH OF AST BLOCK CALL $DEACB ;DEALLOCATE IT CALLR $SETRT ;INSURE RESCAN OF TASK 20$: TST $TKNPT ;TKTN INSTALLED ? BEQ 10$ ;IF EQ NO, DEACLLOCATE PACKET MOV #T.NDEB,R3 ;NO DEBUGGER SPECIFIED MOV T.NAM+2(R5),R4 ;GET SECOND HALF OF TASK NAME MOV T.NAM(R5),R5 ;AND FIRST HALF CALLR $DVMG1 ;REQUEST TKTN USING AST BLOCK ;+ ; **-$GENBF-GENERAL BUFFERED I/O COMPLETION ; ; THIS ROUTINE IS CALLED TO TRANSFER KERNEL AST CONTROL TO A DRIVER ; FOR PROCESSING OF FUNCTIONS WHICH MUST BE DONE WITH TASK CONTEXT ; LOADED. THE AST CONTROL BLOCK IS AS FOLLOWS: ; ; +-----------------------------+ ; ! LINK WORD ! ; +-----------------------------+ ; ! A.BYT=0 ! A.CBL=AK.GBI ! ; +-----------------------------+ ; ! SUBROUTINE KISAR5 BIAS ! ; +-----------------------------+ ; ! SUBROUTINE ADDRESS ! ; +-----------------------------+ ; ; INPUTS: ; ; R0=ADDRESS OF AST CONTROL BLOCK ; ; OUTPUTS: ; ;+ $GENBF::SAVNR ;SAVE NON-VOLATILE REGISTERS MOV R0,R3 ;COPY AST CONTROL BLOCK ADDRESS MOV $TKTCB,R0 ;GET CURRENT TASK TCB POINTER CALL $SETCR ;FORCE RE-DISPATCHING OF PROCESSOR MOV 4(R3),KISAR5 ;MAP TO DRIVER ROUTINE .IF DF K$$DAS MOV 4(R3),KINAR5 ;MAP TO DRIVER ROUTINE (I SPACE) .ENDC ; DF K$$DAS CALLR @6(R3) ;CALL DRIVER ACCEPTANCE ROUTINE ;+ ; **-$FINBF-FINISH TERMINAL INPUT BUFFERED I/O ; ; THIS ROUTINE IS CALLED TO COMPLETE A BUFFERED TERMINAL INPUT ; REQUEST THAT HAS BEEN PLACED IN THE AST QUEUE, OR TO COMPLETE AN I/O ; REQUEST FOR A TASK WHICH MAY HAVE UNMAPPED ITS I/O STATUS BLOCK. ; ; INPUTS: ; ; R0=ADDRESS OF I/O PACKET. ; R4=0 FOR BUFFERED I/O OR 100 FOR POSSIBLE UNMAP OF IOSB. ; ; REQUIRED I/O PACKET FIELDS: ; ; I.FCN+1=I/O FUNCTION CODE OF REQUEST ; I.PRM=RELATIVE KISAR6 BIAS OF USER BUFFER ; I.PRM+2=KISAR6 DISPLACEMENT OF USER BUFFER ; I.PRM+6=FIRST I/O STATUS WORD ; I.PRM+10=2ND I/O STATUS WORD (AND COUNT FOR $BLXIO TRANSFER) ; I.PRM+12=PTR TO LINKED LIST OF BUFFERS OR 0 IF NONE ; I.PRM+14=KISAR5 BIAS OF DRIVER BUFFER ; I.PRM+16=PCB ADDRESS FOR PARTITION OF TRANSFER ; ; NOTE: ONLY THE I/O STATUS IN I.PRM+6 AND I.PRM+10 IS REQUIRED ; IF R4=100. ; OUTPUTS: ; ; THE BUFFERED I/O REQUEST IS COMPLETED AND $IOFIN IS CALLED. THE ; DRIVER IS CALLED TO DEALLOCATE ANY BUFFERS. IF THE BUFFER ADDRESS ; IS ODD, THE BUFFER IS NOT COPIED AND INSTEAD THE DRIVER IS CALLED ; DIRECTLY. THIS CASE ALLOWS FOR NON-STANDARD BUFFER FORMATS. THE ; DRIVER IS RESPONSIBLE FOR TRANSFERRING THE DATA TO THE USER BUFFER. ; IF THE PCB ADDRESS IS ODD, THE BUFFER IS IN SECONDARY POOL. ;- .ENABL LSB $FINBF::SAVNR ;SAVE NONVOLITILE REGISTERS MOV I.PRM+16(R0),R1 ;GET ADDRESS OF BUFFER REGION BIC #1,R1 ;CLEAR SECONDARY POOL INDICATOR CALL $TSPAR ;BUFFER RESIDENT ? BCC 5$ ;IF CC YES BR 50$ ;IF CS NO, LOAD AST QUEUED $FINDI::SAVNR ;SAVE NON-VOLATILE REGISTERS 5$: MOV R0,R3 ;COPY I/O PACKET ADDRESS BIT #1,(R3) ;IS THIS A REGION LOAD AST? BNE 10$ ;IF NE YES, DON'T WRITE I/O STATUS BLOCK MOV I.IOSB(R3),R0 ;PICK UP VIRTUAL IOSB ADDRESS BEQ 10$ ;IF EQ NONE SPECIFIED MOV I.PRM+6(R3),-(SP) ;PUSH FIRST WORD OF I/O STATUS MTPD$ (R0)+ ;WRITE IN USER IOSB (ANY TRAP IGNORED) MOV I.PRM+10(R3),-(SP) ;PUSH SECOND WORD OF I/O STATUS MTPD$ (R0)+ ;WRITE IN USER IOSB+2 (ANY TRAP IGNORED) CLR I.IOSB+4(R3) ;NO I/O STATUS BLOCK FOR $IOFIN 10$: ASSUME AK.BUF,200 ;BUFFERED I/O LOW BITS MUST BE ZERO TSTB R4 ;BUFFERED I/O? BNE 30$ ;IF NE NO MOV I.TCB(R3),R5 ;RETRIEVE TASK TCB ADDRESS DECB T.TIO(R5) ;DECREMENT BUFFERED I/O COUNT INCB T.IOC(R5) ;INCREMENT OUTSTANDING I/O COUNT MOV R3,-(SP) ;SAVE I/O PACKET ADDRESS ADD #I.PRM+16,R3 ;POINT TO PCB ADDRESS MOV (R3),R5 ;SAVE PCB ADDRESS (I.PRM+16) MOV R5,R2 ;COPY PCB ADDRESS BIC #1,R2 ;CLEAR POSSIBLE SEC POOL BUFFER FLAG ADD P.REL(R2),-16(R3) ;MAKE TASK BUFFER BIAS ABSOLUTE CLR (R3) ;CLEAR PCB ADDRESS WORD (I.PRM+16) TST -(R3) ;BACKUP POINTER (I.PRM+14) MOV -(R3),R2 ;PICK UP INPUT BUFFER ADDRESS (I.PRM+12) BEQ 20$ ;IF EQ THERE IS NONE MOV -10(R3),R4 ;GET START ADDR OF USER BUFFER .IF DF T$$ACD!T$$TSA BIT #1,R5 ;BUFFER IN SECONDARY POOL? BNE 12$ ;IF NE YES BIT #1,R2 ;NON-STANDARD BUFFER FORMAT? BNE 17$ ;IF NE YES, BYPASS BUFFER COPY CODE .ENDC ;T$$ACD!T$$TSA 11$: BIT #1,R5 ;BUFFER IN SECONDARY POOL? BEQ 13$ ;IF EQ NO 12$: MOV R2,R1 ;BUFFER ADDRESS IS MAPPING BIAS MOV #120000,R2 ;SET APR5 DISPLACEMENT BR 14$ ;TRANSFER USING SEC POOL BUFFER 13$: CMP R2,#120000 ;BUFFER IN DRIVER SPACE? BLO 15$ ;IF LO NO MOV R2,R1 ;COPY BUFFER ADDRESS BIC #77,R1 ;REMOVE DISPLACEMENT IN BLOCK BITS SUB #120000,R1 ;CALC OFFSET IN DRIVER PAR IN BYTES SUB R1,R2 ;REDUCE ADDRESS TO FIT IN KERNEL 5 ASL R1 ;CONVERT BYTE OFFSET TO 32W BLOCKS ASL R1 ; SWAB R1 ; ADD 2(R3),R1 ;CALCULATE PHYSICAL MEMORY OFFSET 14$: MOV R1,KISAR5 ;MAP BUFFER 15$: MOV (R2)+,-(SP) ;SAVE POINTER TO NEXT BUFFER MOV (R2)+,R0 ;PICK UP SIZE OF BLOCK SUB #4,R0 ;REDUCE COUNT BY HEADER BYTES SUB R0,-(R3) ;IS THERE THAT MUCH LEFT? BCC 16$ ;IF CC YES ADD (R3),R0 ;ELSE SET CORRECT COUNT CLR (R3) ;CLEAR REMAINING BYTE COUNT 16$: MOV -10(R3),R3 ;PICK UP KISAR6 BIAS (I.PRM) CALL $BLXIO ;TRANSFER TO USER BUFFER MOV (SP)+,R2 ;RETRIEVE POINTER TO NEXT BUFFER MOV (SP),R3 ;RETRIEVE I/O PACKET POINTER ADD #I.PRM+10,R3 ;POINT TO BYTE COUNT TST (R3)+ ;MORE TO GO? (I.PRM+10) BNE 11$ ;IF NE YES 17$: MOV (R3),R0 ;POINT TO FIRST BUFFER (I.PRM+12) MOV @I.UCB-(R3),R2 ;POINT TO DRIVER DCB MOV D.PCB(R2),R3 ;POINT TO DRIVER PCB .IF DF K$$DAS MOV P.REL(R3),KDSAR5 ;MAP DRIVER IN DATA SPACE .ENDC MOV P.REL(R3),KINAR5 ;MAP DRIVER IN INSTR SPACE MOV D.DSP(R2),R2 ;POINT TO DRIVER DISPATCH TABLE CALL @D.VDEB(R2) ;CALL DRIVER DEALLOCATION ROUTINE 20$: MOV (SP)+,R3 ;RESTORE PACKET ADDRESS TST (R3) ;REGION LOAD AST ? BNE 40$ ;IF NE YES, RE-QUEUE TASK AST 30$: CALLR $IOFIN ;COMPLETE I/O REQUEST 40$: MOV I.TCB(R3),R0 ;SET TCB ADDRESS MOVB #AK.DIO,A.CBL(R3) ;CHANGE AST TYPE TO "DELAYED ;I/O COMPLETION" CALLR $REQUE ;RE-QUEUE TASK LEVEL AST 50$: INCB T.TIO(R5) ;RE-COUNT BUFFERED I/O ;FORCE I/O RUNDOWN IF TASK ;EXITS DURING LOAD AST RETURN ; .DSABL LSB ; ; EXECUTIVE IDLE LOOP ; ; THE EXECUTIVE IDLE LOOP IS ENTERED WHEN THERE ARE NO RUNNABLE TASKS. ; THE NULL TCB AT THE END OF THE TASK LIST IS ALWAYS GUARANTEED TO BE ; BLOCKED. TWO FLAGS ARE SET FOR OTHER EXECUTIVE ROUTINES IN THE IDLE ; LOOP. ; ; 1. THE ADDRESS OF THE NULL TCB (#$ACTHD) IS SET INTO THE RESCHEDULE ; POINTER ($RQSCH) TO PREVENT $DIRXT FROM EVER RETURNING TO SYSTEM ; STATE WHILE THE EXEC IS IDLE. THIS FORCES EXECUTION BACK TO THE ; IDLE LOOP IN LIEU OF A REAL SCHEDULE REQUEST. ; ; 2. AN IDLE FLAG IS SET ($IDLFL) FOR THE FORK ROUTINES TO CAUSE THEM ; TO FORCE CONTROL BACK TO $DIRXT WHEN NECESSARY TO DEQUEUE A ; FORK. (IT IS IMPOSSIBLE FOR THE IDLE LOOP TO ALWAYS RETURN TO ; $DIRXT WHEN NECESSARY BECAUSE OF A WINDOW BETWEEN THE CHECK OF ; THE FORK LIST AND THE WAIT INSTRUCTION.) ; ; THE STACK CANNOT BE USED IF $IDLFL IS SET TO A ONE AND THE PRIORITY ; IS OTHER THAN PR7, BECAUSE WE COULD SUSTAIN AN INTERRUPT RESULTING ; IN A FORK WHICH WOULD FORCE $QFORK TO JAM AN ADDRESS DIRECTLY INTO ; THE STACK. IF WE ARE USING THE STACK, THEN IT WOULDN'T KNOW WHERE ; TO PUT THE ADDRESS. ; .ENABL LSB IDOL: MOV #$ACTHD,@$RQSCH ;PREVENT $DIRXT RETURN TO USER STATE CLRB @$CURPR ;CLEAR CURRENT TASK PRIORITY ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 31. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH31==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL .IF DF M$$PRO MOV @#$TKTCB,R0 ;;;GET CURRENT TASK ; BM079 BEQ 40$ ;;;IF EQ NO CURRENT TASK BIT @$CPCRM,T.RRM(R0) ;CAN THIS TASK RUN ON THIS CPU? BNE 72$ ;IF NE NO -- REMOVE HIS CONTEXT BIT #TS.BLC,T.STAT(R0) ;;;POSSIBLE FUTURE MAPPING CHANGE? BNE 72$ ;;;IF NE YES -- SAVE THE CONTEXT BIT $CPBIT,$URMST ;ARE WE GOING OFFLINE? BEQ 72$ ;IF EQ YES -- REMOVE CONTEXT BIS #TS.RUN,T.STAT(R0) ;;;SHOW CURRENT TASK BELONGS TO US ; RE-ENTRY POINT AFTER STORING TASK CONTEXT IDLE1: ;;;REF. LABEL FOR CONTEXT SWITCH 40$: MTPS #PR7 ;;;UP OUR PRIORITY BIT $CPBIT,$URMST ;;;ARE WE GOING OFFLINE? BNE 42$ ;;;IF NE NO CALL $OLRNT ;;;TELL HRC... WE MADE IT THIS FAR ULOCK$ $EXECL,WAIT ;;;CLEAR OUT AND LET THE WORLD IN HALT ;;;COME TO A DEAD STOP! 42$: DECB $IDLFL ;;;SHOW IN IDLE LOOP - UNINTERRUPTABLE ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 33. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH33==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL MOV #$IDLPT,R1 ;;;SET UP FOR LIGHT PATTERN ULOCK$ $EXECL,WAIT ;;;UNLOCK EXECUTIVE JMP DIRXT2 ;;;CHECK FOR WAITING FORKS .IFF MOV #$IDLPT,R1 ;;;SET FOR IDLE LOOP LIGHT PATTERN INCB $IDLFL ;;;SHOW IN IDLE LOOP TST $FRKHD ;;;ANYTHING IN FORK LIST BEQ IDLE ;;;IF EQ NO -- ENTER IDLE LOOP ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 33. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH33==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL CLRB @#$IDLFL ;;;NOT IN IDLE LOOP NOW ; BM079 JMP $DIRXT ;;;EXECUTE THE FORKS ;;;ENTER EXECUTIVE .ENDC ; INTERMEDIATE TARGET TO JUMP TO STORE CONTEXT 72$: JMP STCTX ;GO STORE CONTEXT OF TASK IDLE: CACHE$ RESTOR ;RESTORE CACHE TO NON-BYPASS MOV (R1)+,(R1) ;RESTORE IDLE PATTERN DECB $IDLCT ;TIME TO MOVE PATTERN? BGE 45$ ;IF GE NO MOVB #2,$IDLCT ;RESET COUNT ASLB (R1)+ ;MOVE PATTERN ($IDLPT) RORB (R1) ;($IDLPT+1) ADCB -(R1) ;($IDLPT) 45$: MOV (R1),R0 ;PUT IT WHERE IT CAN BE SEEN ($IDLPT) MOV R0,-(R1) ;SAVE IT FOR NEXT TIME WAIT ; ; IF $IIPND HAS ANY OF OUR URMS SET, WE SHOULDN'T BE IN THE IDLE LOOP. ; IF WE HAVE JUST POWERFAILED, THEN THIS CODE PATH MAY BE TAKEN. IF ; NOT, WE SHOULD NEVER EXECUTE IT. STILL, ITS NICE BELT AND SUSPENDERS ; TECHNIQUE. NOT MUCH ELSE TO DO IN THE IDLE LOOP. ; .IF DF M$$PRO CACHE$ BYPASS ;MAKE SURE WE GET THE REAL THING BIT @$CPURM,$IIPND ;ANY WORK FOR US? BEQ IDLE ;IF EQ NO, IDLE AROUND SOME MORE JMP DIRXT2 ;GO FIND OUT FOR SURE .IFF BR IDLE ;IF NO MULTIPROCESSING .ENDC .DSABL LSB ;+ ; **-$SGFIN-SEGMENT FAULT AND TRAP 4 INTERCEPT ROUTINE ; ; THIS ROUTINE IS A CO-ROUTINE WHICH SETS UP TO IGNORE SEGMENT FAULTS ; AND TRAPS THROUGH 4. ; ; INPUTS: ; ; NONE. ; ; OUTPUTS: ; ; NONE. ;- $SGFIN::MOV @#4,-(SP) ;SAVE CONTENTS OF TRAP 4 VECTOR .IF DF P$$D70 MOV $SGFFR,-(SP) ;SAVE LAST $SGFIN FRAME POINTER MOV @#114,-(SP) ;SAVE MAIN MEMORY TIMEOUT AND PARITY MOV 6(SP),-(SP) ;COPY RETURN ADDRESS MOV @#250,10(SP) ;SAVE SEGMENT TRAP ADDRESS MOV #20$,@#114 ;TRAP THESE FAULTS .IFF MOV 2(SP),-(SP) ;COPY RETURN ADDRESS MOV @#250,4(SP) ;SAVE CONTENTS OF SEGMENT FAULT VECTOR .IFTF MOV #10$,@#4 ;POINT TO ROUTINE TO SET CARRY MOV #10$,@#250 ; ; ; CONTENTS OF STACK AT THIS POINT: ; ; 0(SP)=COROUTINE RETURN ADDRESS TO CALLER. ; 2(SP)=CONTENTS OF @#114 (IF DF P$$D70) ; 4(SP)=SAVE $SGFFR CELL (IF DF P$$D70) ; 6(SP)=CONTENTS OF @#4 ; 10(SP)=CONTENTS OF @#250 ; .IFT MOV SP,$SGFFR ;SAVE FRAME POINTER ADD #6,$SGFFR ;ADJUST TO POINT TO SAVED TRAP 4 .IFTF CALL @(SP)+ ;RETURN TO CALLER .IFT MOV (SP)+,@#114 ;RESTORE MAIN MEMORY TIMEOUT TRAP MOV (SP)+,$SGFFR ;RESTORE SAVED FRAME POINTER .IFTF MOV (SP)+,@#4 ;RESTORE TRAP 4 VECTOR BIC #160000,@#SR0 ;UNFREEZE MEMORY MANAGEMENT UNIT MOV (SP)+,@#250 ;RESTORE SEGMENT FAULT VECTOR RETURN ;RETURN TO CALLER'S CALLER 10$: ;REFERENCE LABEL .IFT ; ; TRAP 4 SERVICE FOR 11/70 CLASS MACHINES. ; ; THIS TRAP SERVICE RESETS THE VECTOR AT FOUR, AND THEN ATTEMPTS TO ; CLEAR THE CPU ERROR REGISTER. IF THE REGISTER ISN'T THERE, WE WILL ; TRAP THRU FOUR, AND GO TO 15$, WHERE WE WILL CLEAR THE EQUAL BIT, ; SET THE CARRY BIT, AND RTI. AFTER THE ATTEMPT TO CLEAR THE CPU ERROR ; REGISTER, WE CHECK THE CARRY TO SEE IF IT WAS REALLY THERE, AND IF ; IT WAS, THEN WE CHECK IT TO SEE IF THIS WAS ONE OF THE CONDITIONS ; THAT WE EXPECT IN $SGFIN. IF IT ISN'T, THEN WE ACT LIKE THIS WAS ; A NORMAL TRAP TO FOUR. ; MOV #15$,@#4 ;RESET TRAP TO FOUR ADDRESS CLC ;SET UP CARRY PROPERLY NOW BIC #60,@#177766 ;CLEAR OUT CPU ERROR REGISTER BCS 12$ ;IF CS REGISTER ISN'T THERE BEQ 12$ ;IF EQ WE CLEARED IT ALL OUT ; ; HERE WE HAVE FOUND A PROBLEM: WE HAVE TAKEN A TRAP THROUGH VECTOR ; LOCATION 4, BUT THE REASON WAS NOT FOR NON-EXISTANT MEMORY. IN ; THIS CASE, WE WISH TO SIMULATE A TRAP THROUGH THE CONTENTS OF VECTOR ; FOUR PRIOR TO THE TIME THAT $SGFIN PLACED ITS OWN VALUE IN IT. THIS ; IS POINTED TO ON THE STACK BY THE $SGFFR POINTER. IT SEEMS REASONABLE ; TO SIMPLY DISPATCH THROUGH THAT LOCATION, WHICH WE WILL DO. IF THIS ; IS NOT A GOOD IDEA, THIS IMPLEMENTATION WILL ALLOW UNTHREADING THE ; STACK UNTIL THE ULTIMATE RESOLUTION OF THE NESTED CALLS TO $SGFIN ; IS EFFECTED. ; MOV @$SGFFR,-(SP) ;GET ADDRESS TO JUMP TO JMP @(SP)+ ;JUMP THERE 11$: MOV #104001,@#177744 ;CLEAR OUT MEMORY SYSTEM ERROR REGISTER 12$: MOV #10$,@#4 ;RESET TRAP 4 (WHETHER IT NEEDS IT OR NOT) .IFTF 15$: BIC #4,2(SP) ;CLEAR EQUAL BIT BIS #1,2(SP) ;SET CARRY BIT RTI .IFT ; ; TRAP 114 SERVICE ; ; THIS TRAP SERVICE ACCEPTS TRAPS TO 114 ON PDP-11/70 CLASS MACHINES ; SO THAT ATTEMPTS TO REFERENCE NON-EXISTANT MEMORY BELOW THE SYSTEM ; SIZE REGISTER DOESN'T LOOK LIKE A PARITY ERROR. THIS SERVICE ALSO ; ATTEMPTS TO VERIFY IF THE CAUSE OF THE TRAP TO 114 IS IN FACT A ; NON-EXISTANT MEMORY CONDITION, OR IF IT WAS SOME OTHER PROBLEM. ; IF IT WAS SOME OTHER PROBLEM, TRANSFER IS MADE TO THE PARITY ERROR ; SERVICE ROUTINE. IF IT WAS NON-EXISTANT MEMORY, THEN THE REGISTER ; IS CLEARED AND THE NORMAL CODE FLOW REENTERED. ; ; A SPECIAL CASE EXISTS IN THE CASE WHERE A TRAP 114 OCCURRED, AND WE ; ARE NOT ON A SYSTEM WITH A MEMORY SYSTEM ERROR REGISTER. IN THIS ; CASE, THE CMP ACCESS WILL FAIL, TRAPPING THRU 4, WHICH WILL ENCOUNTER ; THE CODE IN $SGFIN MENTIONED ABOVE. THIS CODE WILL CLEAR THE EQ BIT, ; SO THAT THE COMPARISON WILL FAIL, CAUSING A TRANSFER TO THE PARITY ; ERROR SERVICE ROUTINE. THIS IS THE DESIRED RESULT, SINCE THE ONLY WAY ; WE COULD TRAP TO 114 ON A MACHINE WITHOUT A MEMORY SYSTEM ERROR REGISTER ; (OR SYSTEM SIZE REGISTER) WAS TO ENCOUNTER A REAL PARITY ERROR. ; 20$: CMP #104001,@#177744 ;IS THIS MAIN MEMORY TIMEOUT? BEQ 11$ ;IF EQ YES -- SET CARRY AND RETURN .IF DF U$$BME BCS 25$ ; IF CS, MEM SYS ERR REGISTER DOESN'T EXIST BIT #20000,@#177744 ; UNIBUS PARITY ERROR? BEQ 25$ ; IF EQ, NOPE, SOMETHING ELSE ... MOV @#177744,@#177744 ; CLEAR OUT THE ERROR REGISTER BIS #2,2(SP) ; SET THE V BIT RTI ; BACK TO SOURCE 25$: .ENDC ;DF,U$$BME .IF DF P$$RTY JMP $PARER ;NO -- THIS IS PARITY ERROR .IFF ; DF P$$RTY BGCK$A BF.PAR,BE.SGN,HALT ;PARITY ERROR, P$$RTY NOT DEFINED .ENDC ; DF P$$RTY .ENDC ;+ ; **$SWSTK-SWITCH STACKS ; ; THIS ROUTINE IS CALLED FROM TASK LEVEL TO SWITCH TO THE SYSTEM ; STACK THUS INHIBITING TASK SWITCHING. THE CALLING TASK MUST BE ; PRIVILEGED IF RUNNING IN A MAPPED SYSTEM AND MAPPED TO THE EXEC. ; CONTROL IS PASSED HERE FROM DRDSP AFTER THE TRAP HAS OCCURED AND ; $DIRSV HAS BEEN CALLED. ; ; CALLING SEQUENCE: ; ; EMT 376 ;TRAP TO $EMSST IN DRDSP ; .WORD ADDR ;ADDRESS FOR RETURN TO USER STATE ; ; INPUTS AT THIS POINT: ; ; R3=ADDRESS OF PC WORD OF TRAP ON STACK + 2 ; ; MAPPED SYSTEM: ; ; 22(SP)=PS PUSHED BY TRAP ; 20(SP)=PC PUSHED BY TRAP ; 16(SP)=SAVED R5 ; 14(SP)=SAVED R4 ; 12(SP)=SAVED R3 ; 10(SP)=SAVED R2 ; 06(SP)=SAVED R1 ; 04(SP)=SAVED R0 ; 02(SP)=RETURN ADDRESS FOR SYSTEM EXIT ; 00(SP)=104376 ; ; OUTPUTS: ; ; THE USER IS CALLED BACK ON THE SYSTEM STACK WITH ALL REGISTERS ; PRESERVED. TO RETURN TO TASK LEVEL THE CALLER MERELY EXECUTES ; A RETURN. ; ; NOTE: PRIVILEGED TASKS MAY ONLY CALL $SWSTK FROM SUPERVISOR ; MODE IF BOTH SUPERVISOR MODE AND KERNEL DATA SPACE ARE ; SUPPORTED IN THE EXEC. FURTHERMORE, THEY MUST ONLY DO ; SO WITH CODE RUNNING IN APRS 5, 6 & 7. ;- $SWSTK::BICB #357,(R3) ;SET INITIAL PS WORD .IF DF K$$DAS&S$$LIB TST $STACK-2 ;CALL FROM SUPERVISOR MODE? BMI 5$ ;IF MI NO MOV SDSAR5,KDSAR5 ;COPY SUPERVISOR MOV SDSAR6,KDSAR6 ;DATA MAPPING MOV SISAR5,KINAR5 ;COPY SUPER INSTR MAPPING MOV SISAR6,KINAR6 ; MOV SISAR7,KINAR7 ; BR 10$ ;FINISH IN COMMON CODE .ENDC 5$: MOV #UINAR5,R5 ;POINT TO USER I APR 5 .IF DF K$$DAS .IF DF U$$DAS MOV UDSAR0-UINAR0(R5),KDSAR5 ;SET UP KERNEL DATA 5 .IFF ; DF U$$DAS MOV (R5),KDSAR5 ;SET UP KERNEL DATA 5 .ENDC ; DF U$$DAS .IFTF ; DF K$$DAS MOV (R5)+,KINAR5 ;SET UP KERNEL INST 5 .IFT ; DF K$$DAS .IF DF U$$DAS MOV UDSAR0-UINAR0(R5),KDSAR6 ;SET UP KERNEL DATA 6 .IFF ;DF U$$DAS MOV (R5),KDSAR6 ;SET UP KERNEL DATA 6 .ENDC ;DF U$$DAS .ENDC ;DF K$$DAS .IF DF K$$DAS&U$$DAS MOV (R5)+,KINAR6 ;SET UP KERNEL INST 6 MOV (R5)+,KINAR7 ;SET UP KERNEL INST 7 .IFF MOV (R5),KINAR6 ;SET UP KERNEL INST 6 .ENDC ;DF K$$DAS&U$$DAS 10$: MOV -(R3),R5 ;PICK UP TRAP PC WORD .IF DF U$$DAS!K$$DAS&S$$LIB MFPI (R5)+ ;GET ADDRESS FOR RETURN TO USER STATE MOV (SP)+,(R3) ;FROM CORRECT SPACE AND SET IT .IFF ; DF U$$DAS!K$$DAS&S$$LIB MOV (R5)+,(R3) ;SET ADDRESS FOR RETURN TO USER STATE .ENDC ; DF U$$DAS!K$$DAS&S$$LIB MOV R5,(SP) ;SET CALLER'S ADDRESS MOV -(R3),R5 ;RESTORE R5 MOV 12(SP),R3 ;RESTORE R3 ;+ ; ** W A R N I N G ** ; ; SPM HOOKPOINT NUMBER 70. ; ; DO NOT CHANGE THE INSTRUCTION FOLLOWING ; LABEL WITHOUT CHECKING SPM ;- $SPH70==. ;SPM CHANGES THE INSTRUCTION AT ;THE LOCATION OF THIS LABEL CALLR @(SP)+ ;CALL THE CALLER ;+ ; **-$LSUPD-LOAD SUPERVISOR DATA SPACE ; ; THIS ROUTINE IS CALLED BEFORE TRANSFERRING CONTROL TO A TASK IN ; SUPERVISOR MODE TO LOAD SUPERVISOR D SPACE FROM USER I SPACE. ; ; INPUTS: ; ; NONE. ; ; OUTPUTS: ; ; R2 AND R3 ARE PRESERVED. ;- .IF DF S$$LIB $LSUPD::BIC #^CPSMODE&PMODE,PS ;SWITCH PREVIOUS MODE TO SUPERVISOR $LSUP1:: ;GLOBAL ENTRY WHICH DOESN'T AFFECT ;MODE BITS IN THE PSW LSUPD1: BIS #10,SR3 ;ENABLE CSM INSTRUCTION MOV #UISDR0,R0 ;POINT TO USER D PDR0 MOV #SDSDR0,R1 ;POINT TO SUPER D PDR0 MOV R3,-(SP) ;SAVE A WORK REGISTER .IF DF X$$HDR MOV KISAR6,-(SP) ;SAVE CURRENT EXEC MAPPING MOV $SAHDB,KISAR6 ;MAP TO HEADER IF EXTERNAL .IFTF ; DF X$$HDR MOV $SAHPT,R3 ;GET ADDRESS OF TASK HEADER MOVB H.SMAP(R3),R3 ;GET MAPPING MASK BNE 30$ ;IF NE MAPPING IS MIXED ; THIS SECTION HANDLES THE UNMIXED CASE (ALL SUPER D MAPPED TO USER D) ; IN STRAIGHT LINE CODE FOR PERFORMANCE SAKE. 10$: MOV (R0)+,(R1)+ ;COPY USER I TO SUPER D SPACE MOV (R0)+,(R1)+ ; MOV (R0)+,(R1)+ ; MOV (R0)+,(R1)+ ; MOV (R0)+,(R1)+ ; MOV (R0)+,(R1)+ ; MOV (R0)+,(R1)+ ; MOV (R0),(R1) ; CMP R1,#SDSAR7 ;DONE YET? BEQ 20$ ;IF EQ YES MOV #UISAR0,R0 ;POINT TO USER I APR0 MOV #SDSAR0,R1 ;POINT TO SUPER D APR0 BR 10$ ;PERFORM COPY 20$: .IFT ; DF X$$HDR MOV (SP)+,KISAR6 ;RESTORE PREVIOUS EXEC MAPPING .IFTF ; DF X$$HDR MOV (SP)+,R3 ;RESTORE WORK REGISTER RETURN ; ; THIS SECTION HANDLES THE MIXED CASE WHERE SOME OF SUPER D IS MAPPED ; TO USER D AND SOME IS MAPPED TO SUPER I BY INTERPRETING H.SMAP 30$: MOV R2,-(SP) ;SAVE ANOTHER REGISTER MOV #SISDR0,R2 ;POINT TO SUPER I REGISTERS BIS #100000,R3 ;SET DONE FLAG BIT INTO REGISTER ASLB R3 ;ADJUST REGISTER FOR FACT THAT ;BIT ZERO OF MAP CORRESPONDS TO APR1 40$: ASR R3 ;CHECK NEXT BIT (NEXT APR) BCC 50$ ;IF CC NEXT APR MAPS USER D SPACE MOV SISAR0-SISDR0(R2),SDSAR0-SDSDR0(R1) ;SET ADDRESS MOV (R2)+,(R1)+ ;SET ACCESS AND LENGTH TST (R0)+ ;ADJUST USER D POINTER BR 60$ ;ON TO NEXT ONE 50$: MOV UISAR0-UISDR0(R0),SDSAR0-SDSDR0(R1) ;SET ADDRESS MOV (R0)+,(R1)+ ;SET ACCESS AND LENGTH TST (R2)+ ;ADJUST SUPER I POINTER 60$: TSTB R3 ;MORE TO GO ? BPL 40$ ;IF PL YES MOV (SP)+,R2 ;RESTORE REGISTERS .IFT ; DF X$$HDR MOV (SP)+,KISAR6 ;RESTORE PREVIOUS EXEC MAPPING .ENDC ; DF X$$HDR MOV (SP)+,R3 ;FOR RETURN RETURN ; .ENDC ;+ ; **-CKMAP-CHECK TASK MAPPING TO DETERMINE IF IT CAN RUN NOW. ; ; THIS ROUTINE DETERMINES IF THERE ARE MULTIPLE RUNNING TASKS MAPPED ; TO THE SAME REGION. ; ; INPUTS: ; ; R2=HEADER ADDRESS FOR TASK BEING TESTED FOR ELIGIBILITY TO RUN. ; R5=TCB ADDRESS FOR TASK BEING TESTED FOR ELIGIBILITY TO RUN. ; ; OUTPUTS: ; ; C=0 IF TASK CAN RUN NOW. ; C=1 IF TASK CANNOT RUN NOW BECAUSE THERE ARE OTHER RUNNING ; TASKS MAPPED TO A REGION WHICH THIS TASK IS MAPPED TO. ; ;- $CKMAP:: .IF DF M$$PRO CLR -(SP) ;ASSUME TASK CAN RUN NOW MOV R0,-(SP) ;SAVE REGISTERS MOV R1,-(SP) ; MOV R2,-(SP) ; MOV R3,-(SP) ; MOV R4,-(SP) ; .IF DF X$$HDR MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING .IFTF ; DF X$$HDR MOV H.WND(R2),R0 ;POINT TO # OF WINDOWS IN TASK TO BE RUN MOV (R0)+,-(SP) ;GET THE NUMBER OF WINDOWS 10$: ;REFERENCE LABEL .IFT ; DF X$$HDR MOV #$DICSV,R3 ;POINT TO INTERMEDIATE SAVE AREA MOV R0,(R3)+ ;SAVE WINDOW ADDRESS .REPT MOV (R0)+,(R3)+ ;COPY ADDR WNDW TO SAVE AREA .ENDR SUB #W.BLGH,R3 ;POINTER TO BEGINNING OF WINDOW AREA MOV R3,R0 ;POINT TO WINDOW IN SAVE AREA .IFTF ; DF X$$HDR TST (R0) ;IS WINDOW MAPPED? BEQ 90$ ;IF EQ NO .IFTF ; DF X$$HDR MOV #M$$PRO,R1 ;GET THE NUMBER OF PROCESSORS MOV #$TKTAB,R2 ;POINT TO TCB TABLE 20$: MOV (R2)+,R3 ;GET NEXT TCB ADDRESS BEQ 80$ ;IF EQ THERE IS NO CURRENT TASK ON PROC CMP R5,R3 ;IS THIS OUR TCB? BEQ 80$ ;IF EQ YES SKIP IT BIT #T4.SNC,T.ST4(R3) ;DOES TASK SYNCHRONIZE THRU COMMONS? BEQ 80$ ;IF EQ NO BIT #^C,T.STAT(R3) ;IS TASK BLOCKED? BNE 80$ ;IF NE YES BIT #T2.STP!T2.WFR,T.ST2(R3) ;IS TASK STOPPED OR IN WAITFOR? BNE 80$ ;IF NE YES MOV T.PCB(R3),R3 ;GET ADDRESS OF TASK REGION PCB .IFT ; DF X$$HDR MOV P.REL(R3),KISAR6 ;MAP EXTERNAL HEADER MOV P.HDR(R3),R3 ;GET TASK HEADER ADDRESS BNE 25$ ;IF NE, TASK HAS POOL HEADER MOV #140000,R3 ;OTHERWISE, TASK HAS EXTRNL HEADER 25$: ;REFERENCE LABEL .IFF ; DF X$$HDR MOV P.HDR(R3),R3 ;GET ADDRESS OF TASK HEADER .IFTF ; DF X$$HDR MOV H.WND(R3),R3 ;POINT TO NUMBER OF WINDOWS MOV (R3)+,-(SP) ;GET THE NUMBER OF WINDOWS 30$: CMP (R0),(R3) ;MAPPED TO THE SAME REGION? BNE 70$ ;IF NE NO CMP W.BOFF(R0),W.BOFF(R3) ;DOES TASK TO BE RUN HAVE A REGION ;WHICH OVERLAPS THE REGION OF A TASK ;RUNNING ON ANOTHER PROCESSOR? BEQ 60$ ;IF EQ YES BHI 50$ ;IF HI MAYBE MOV W.BOFF(R0),R4 ;SAVE REGION OFFSET FOR TASK TO BE RUN ADD W.BSIZ(R0),R4 ;CALCULATE END OF MAPPED AREA CMP R4,W.BOFF(R3) ;REGIONS OVERLAP? BHI 60$ ;IF HI YES BR 70$ ;REGIONS DO NOT OVERLAP 50$: MOV W.BOFF(R3),R4 ;GET REGION OFFSET FOR RUNNING TASK ADD W.BSIZ(R3),R4 ;CALCULATE END OF MAPPED AREA CMP R4,W.BOFF(R0) ;DO REGIONS OVERLAP? BLOS 70$ ;IF LOS NO 60$: INC 16(SP) ;INDICATE OVERLAP, TASK CANNOT RUN NOW TST (SP)+ ;CLEAN THE STACK BR 100$ ; 70$: ADD #W.BLGH,R3 ;POINT TO NEXT WINDOW IN RUNNING TASK DEC (SP) ;ANY MORE WINDOWS? BNE 30$ ;IF NE YES TST (SP)+ ;CLEAN THE STACK 80$: SOB R1,20$ ;CONTINUE SCAN WITH NEXT RUNNING TASK .IFF ; DF X$$HDR 90$: ADD #W.BLGH,R0 ;POINT TO NEXT WINDOW OF TASK TO BE RUN .IFT ; DF X$$HDR 90$: MOV 2(SP),KISAR6 ;RESTORE POSSIBLE MAPPING TO XTRNL HEADER ADD #W.BLGH,-(R0) ;SET UP POINTER TO NEXT WINDOW MOV (R0),R0 ; .IFTF ; DF X$$HDR DEC (SP) ;ANY MORE WINDOWS? BNE 10$ ;IF NE YES 100$: TST (SP)+ ;CLEAN THE STACK .IFT ; DF X$$HDR MOV (SP)+,KISAR6 ;RESTORE PREVIOUS MAPPING .ENDC ; DF X$$HDR MOV (SP)+,R4 ;RESTORE REGISTERS MOV (SP)+,R3 ; MOV (SP)+,R2 ; MOV (SP)+,R1 ; MOV (SP)+,R0 ; ROR (SP)+ ;CLEAN STACK AND RETURN STATUS IN CARRY RETURN ; .ENDC .END